Comment puis-je remplacer des espaces par de nouvelles lignes sur une entrée comme:
/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5
etc...
Pour obtenir les éléments suivants:
/path/to/file
/path/to/file2
/path/to/file3
/path/to/file4
/path/to/file5
Je poste cette question pour aider d'autres utilisateurs, il n'a pas été facile de trouver une réponse utile sur UNIX SE jusqu'à ce que je commence à taper cette question. Après cela, j'ai trouvé ce qui suit:
Comment puis-je trouver et remplacer par une nouvelle ligne?
Utilisez la commande tr
echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5"\
| tr " " "\n"
Trouvé sur http://www.unix.com/Shell-programming-scripting/67831-replace-space-new-line.html
Dans ce cas, j'utiliserais printf:
printf '%s\n' /path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5
S'il y a des espaces à l'intérieur celui des chemins, vous pouvez citer ce chemin de fichier afin d'éviter qu'il ne soit divisé sur les espaces:
printf '%s\n' /path/to/file '/path/to/file with spaces' /path/to/another/file
Pour transformer le texte en général, tr
est votre meilleur pari, comme indiqué dans une réponse existante.
Soyez pragmatique, utilisez sed !!
sed 's/\s\+/\n/g' file
Ce qui précède dit de remplacer un ou plusieurs espaces (\ s +) par une nouvelle ligne (\ n)
C'est plus ou moins:
'substitute /one space or more/ for /newline/ globally'
En supposant que vous ayez une chaîne avec des espaces comme séparateurs:
newline_separated=${space_separated// /$'\n'}
Cependant, vous posez probablement la mauvaise question. (Pas nécessairement, par exemple, cela pourrait apparaître dans un makefile.) Une liste de noms de fichiers séparés par des espaces ne fonctionne pas vraiment: que faire si l'un des noms de fichiers contient des espaces?
Si un programme reçoit des noms de fichiers comme arguments, ne les joignez pas à des espaces. Utilisation "$@"
pour y accéder un par un. Bien que echo "$@"
affiche les arguments avec des espaces entre les deux, c'est dû à echo
: il affiche ses arguments avec des espaces comme séparateurs. somecommand "$@"
transmet les noms de fichier comme arguments séparés à la commande. Si vous souhaitez imprimer les arguments sur des lignes distinctes, vous pouvez utiliser
printf '%s\n' "$@"
Si vous avez des noms de fichiers séparés par des espaces et que vous souhaitez les placer dans un tableau pour y travailler, vous pouvez utiliser une extension de variable sans guillemets pour diviser la valeur en caractères sur IFS
(vous devrez désactiver extension générique avec set -f
, sinon les motifs glob seront développés dans la valeur):
space_separated_list='/path/to/file1 /path/to/file2 /path/to/file3'
IFS=' '; set -f
eval "array=(\$space_separated_list)"
for x in "${array[@]}"; do …
Vous pouvez l'encapsuler dans une fonction qui restaure le -f
paramètre et la valeur de IFS
quand c'est fait:
split_list () {
local IFS=' ' flags='+f'
if [[ $- = *f* ]]; then flags=; fi
set -f
eval "$1=($2)"
set $flags
}
split_list array '/path/to/file1 /path/to/file2 /path/to/file3'
for x in "${array[@]}"; do …
Comme alternative à tr
de @laconbass, vous pouvez également utiliser xargs
dans ce cas:
echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5"\
| xargs -n1
L'avantage est qu'il fonctionne même avec plusieurs espaces blancs, ce que tr
ne fait pas.
Voici comment je l'ai fait:
echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5" | sed 's/ /\
'/g
Notez l'utilisation de la touche Entrée après la barre oblique inverse dans la commande sed
.
Une autre approche, en supposant que la ligne se trouve dans une variable appelée line
:
for path in $line;do echo $path;done
Cela utilise le fait que Bash divise ses arguments sur les espaces blancs par défaut et que echo
ajoute une nouvelle ligne à son entrée par défaut.
echo Word1 Word2 ... | sed -e 'y/ /\n/;P;D'
est une autre méthode pour transformer des mots séparés par un espace en séparateurs de nouvelle ligne.