diviser la longue ligne sur un délimiteur

21

Quelle commande puis-je utiliser pour diviser une entrée comme celle-ci:

foo:bar:baz:quux

en cela?

foo
bar
baz
quux

J'essaie de comprendre la cutcommande, mais elle ne semble fonctionner qu'avec des quantités fixes d'entrée, comme "1000 premiers caractères" ou "7 premiers champs". Je dois travailler avec une entrée arbitrairement longue.

japreiss
la source
5
Tu veux dire comme tr : '\n' < input?
jw013
Quel shell utilisez-vous? frapper?
glenn jackman

Réponses:

34

Il y a quelques options:

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

Vous pouvez également le faire en pur bash:

while IFS=: read -ra line; do
    printf '%s\n' "${line[@]}"
done
Chris Down
la source
3
Notez que l'utilisation \nde la chaîne de remplacement comme celle-ci fonctionnera dans GNU sed, mais échouera dans la plupart des autres implémentations sed.
wjv
@chrisdown Existe-t-il un moyen de faire fonctionner les deux premiers sous AIX?
cokedude
4
$ line=foo:bar:baz:quux
$ words=$(IFS=:; set -- $line; printf "%s\n" "$@")
$ echo "$words"
foo
bar
baz
quux
glenn jackman
la source
4

Si votre grep le supporte, -ovous pouvez le faire comme ceci:

grep -o '[^:]\+'

Ou avec awk, définissez le séparateur d'enregistrement sur ::

awk -v RS=: 1

Ou avec GNU cut:

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

modifier

Comme indiqué par Chris ci-dessous, cela laissera une nouvelle ligne de fin, cela peut être évité si votre awk prend en charge la spécification en RStant qu'expression régulière (testé avec GNU awk):

awk -v RS='[:\n]' 1
Thor
la source
Votre awkexemple laissera une nouvelle ligne (probablement indésirable) à la fin.
Chris Down
@ChrisDown: vous avez raison, cela peut être évité si RS peut être une expression régulière.
Thor
-1

Dans certaines chaînes, j'ai eu des problèmes avec les solutions ci-dessus. Mais cela a fonctionné pour moi:

echo $string | sed 's/\\n/ /g' | tr " " \\n
Robert
la source
Comme écrit, cela ne transforme pas l'entrée d'exemple OP.
kbulgrien