Supposons que j'ai une sortie d'une commande (telle que ls -1
):
a
b
c
d
e
...
Je veux appliquer une commande (disons echo
) à chacun d'eux, à tour de rôle. Par exemple
echo a
echo b
echo c
echo d
echo e
...
Quelle est la façon la plus simple de faire ça en bash?
ls -1
peut être un exemple ici, mais il est important de se rappeler qu'il n'est pas bon d'analyser la sortie dels
. Voir: mywiki.wooledge.org/ParsingLsRéponses:
C'est probablement le plus simple à utiliser
xargs
. Dans ton cas:L'
-L
indicateur garantit que l'entrée est lue correctement. Depuis la page de manuel dexargs
:la source
ls
fait automatiquement-1
dans un tuyau.ls | xargs -L2 echo
etls -1 | xargs -L2 echo
donne deux sorties différentes. Le premier étant tous sur une seule ligne.xargs
ne peut exécuter que des fichiers exécutables et non des fonctions shell ou des commandes intégrées du shell. Pour le premier, la meilleure solution est probablement celle avecread
une boucle.-L1
sert.Vous pouvez utiliser une opération de préfixe de base sur chaque ligne:
Ou vous pouvez diriger la sortie vers sed pour des opérations plus complexes:
la source
sh: cho: not found a sh: cho: not found
dirait qu'elle prende
in echo pour être une commande sed ou quelque chose.while
boucle.cmd1 | while read line; do cmd2 $line; done
. Ouwhile read line; do cmd2 $line; done < <(cmd1)
qui ne crée pas de sous-shell. Voici la version simplifiée de votresed
commande:sed 's/.*/echo &/'
"$line"
boucle while, afin d'éviter la division des mots.read -r line
pour éviter deread
jouer avec les caractères échappés. Par exempleecho '"a \"nested\" quote"' | while read line; do echo "$line"; done
donne"a "nested" quote"
, qui a perdu son échappatoire. Si nous le faisons,echo '"a \"nested\" quote"' | while read -r line; do echo "$line"; done
nous obtenons"a \"nested\" quote"
comme prévu. Voir wiki.bash-hackers.org/commands/builtin/readVous pouvez utiliser une boucle for :
Notez que si la commande en question accepte plusieurs arguments, utiliser xargs est presque toujours plus efficace car il suffit de générer l'utilitaire en question une fois au lieu de plusieurs fois.
la source
printf '%s\0' * | xargs -0 ...
- sinon, c'est assez dangereux avec les noms de fichiers avec des espaces, des guillemets, etc.Vous pouvez en fait utiliser sed pour le faire, à condition que ce soit GNU sed.
Comment ça fonctionne:
la source
cat /logs/lfa/Modified.trace.log.20150904.pw | sed -r 's/^(.*)(\|006\|00032\|)(.*)$/echo "\1\2\3 - ID `shuf -i 999-14999 -n 1`"/e'
Si cmd a une grande sortie:
la source
cmd
contient des espaces dans sa sortie, le premier échouera.xargs échoue avec des barres obliques inverses, des guillemets. Cela doit être quelque chose comme
Option xargs -0:
ls -1
termine les éléments avec des caractères de nouvelle ligne, donc lestr
traduit en caractères nuls.Cette approche est environ 50 fois plus lente que l'itération manuelle avec
for ...
(voir la réponse de Michael Aaron Safyan ) (3,55s contre 0,066s). Mais pour d'autres commandes d'entrée comme localiser, rechercher, lire à partir d'un fichier (tr \\n \\0 <file
) ou similaire, vous devez travailler avecxargs
comme ceci.la source
Meilleur résultat pour moi:
la source
find . -mindepth 1 -maxdepth 1 -print0 | xargs -0 command
traitera les cas où la sortie dels -1
est ambiguë; utilisez-printf '%P\0'
plutôt que-print0
si vous ne voulez pas de tête./
sur chacun.j'aime utiliser gawk pour exécuter plusieurs commandes sur une liste, par exemple
cependant, la fuite des personnages échappables peut devenir un peu poilue.
la source