podziel długą linię na separatorze

21

Jakiego polecenia mogę użyć do podzielenia danych wejściowych w ten sposób:

foo:bar:baz:quux

zaangażowany w to?

foo
bar
baz
quux

Próbuję rozgryźć cutpolecenie, ale wydaje się, że działa ono tylko ze stałą ilością danych wejściowych, takich jak „pierwsze 1000 znaków” lub „pierwsze 7 pól”. Muszę pracować z dowolnie długim wkładem.

japreiss
źródło
5
Masz na myśli tr : '\n' < input?
jw013,
Jakiej powłoki używasz? grzmotnąć?
glenn jackman

Odpowiedzi:

34

Istnieje kilka opcji:

  • tr : \\n
  • sed 's/:/\n/g'
  • awk '{ gsub(":", "\n") } 1'

Możesz to również zrobić w czystej postaci bash:

while IFS=: read -ra line; do
    printf '%s\n' "${line[@]}"
done
Chris Down
źródło
3
Zauważ, że użycie \ntakiego zastępującego ciągu będzie działać w GNU sed, ale zawiedzie w większości innych implementacji sed.
wjv
@chrisdown Czy istnieje sposób, aby pierwsze dwa działały w systemie AIX?
Cokedude
4
$ line=foo:bar:baz:quux
$ words=$(IFS=:; set -- $line; printf "%s\n" "$@")
$ echo "$words"
foo
bar
baz
quux
Glenn Jackman
źródło
4

Jeśli twój grep obsługuje -o, możesz to zrobić w następujący sposób:

grep -o '[^:]\+'

Lub za pomocą awk, ustawiając separator rekordów na ::

awk -v RS=: 1

Lub z cięciem GNU:

cut -d: --output-delimiter=$'\n' -f1-

Edytować

Jak zauważył Chris poniżej, pozostawi to końcowy znak nowej linii, można tego uniknąć, jeśli awk obsługuje określanie RSjako wyrażenie regularne (testowane z GNU awk):

awk -v RS='[:\n]' 1
Thor
źródło
Twój awkprzykład pozostawi (prawdopodobnie niepożądany) końcowy znak nowej linii.
Chris Down,
@ChrisDown: masz rację, można tego uniknąć, jeśli RS może być wyrażeniem regularnym.
Thor
-1

W niektórych ciągach miałem problem z powyższymi rozwiązaniami. Ale to zadziałało dla mnie:

echo $string | sed 's/\\n/ /g' | tr " " \\n
Robert
źródło
Jak napisano, nie przekształca to przykładowego wejścia OP.
kbulgrien