Comment analyser chaque ligne dun fichier texte comme argument dune commande?

Je « cherche à écrire un script qui prend un nom de fichier .txt comme argument, lit la ligne du fichier par ligne et transmet chaque ligne à une commande. Par exemple, elle exécute command --option "LINE 1", puis command --option "LINE 2", etc. La sortie de la commande est écrit dans un autre fichier. Comment dois-je procéder? Je ne sais pas par où commencer.

Réponse

Utilisez la boucle while read:

: > another_file ## Truncate file. while IFS= read -r LINE; do command --option "$LINE" >> another_file done < file 

Une autre consiste à rediriger la sortie par bloc:

while IFS= read -r LINE; do command --option "$LINE" done < file > another_file 

Le dernier est douvrir le fichier:

exec 4> another_file while IFS= read -r LINE; do command --option "$LINE" >&4 echo xyz ## Another optional command that sends output to stdout. done < file 

Si lune des commandes lit lentrée, ce serait un bon idée dutiliser un autre fd pour lentrée pour que les commandes ne le mangent pas (ici en supposant ksh, zsh ou bash pour -u 3, utilisez <&3 à la place de manière portable):

while IFS= read -ru 3 LINE; do ... done 3< file 

Aileron allié pour accepter les arguments, vous pouvez faire:

#!/bin/bash FILE=$1 ANOTHER_FILE=$2 exec 4> "$ANOTHER_FILE" while IFS= read -ru 3 LINE; do command --option "$LINE" >&4 done 3< "$FILE" 

Lequel pourrait fonctionner comme:

bash script.sh file another_file 

Idée supplémentaire. Avec bash, utilisez readarray:

readarray -t LINES < "$FILE" for LINE in "${LINES[@]}"; do ... done 

Remarque: IFS= peut être omis si cela ne vous dérange pas de couper les valeurs de ligne des espaces de début et de fin.

Réponse

Une autre option est xargs.

Avec GNU xargs:

xargs -a file -I{} -d"\n" command --option {} other args 

{} est lespace réservé pour la ligne de texte.

Autre xargs nont généralement pas -a, -d, mais certains ont -0 pour une entrée délimitée par NUL. Avec ceux-ci, vous pouvez faire:

< file tr "\n" "\0" | xargs -0 -I{} command --option {} other args 

Sur les systèmes conformes à Unix (-I est facultatif dans POSIX et uniquement requis pour les systèmes conformes à UNIX), vous devez prétraiter l’entrée pour citer les lignes au format attendu par xargs:

< file sed "s/"/"\\""/g;s/.*/"&"/" | xargs -E "" -I{} command --option {} other args 

Notez cependant que certaines implémentations de xargs ont une limite très basse sur la taille maximale de largument (255 sur Solaris par exemple, le minimum autorisé par la spécification Unix).

Commentaires

  • réductible à <file xargs -L 1 -I{} command --option {} other args
  • @iruvar, non, cela traiterait les guillemets et supprimerait certains espaces.

Réponse

Garder précisément à la question:

#!/bin/bash # xargs -n param sets how many lines from the input to send to the command # Call command once per line [[ -f $1 ]] && cat $1 | xargs -n1 command --option # Call command with 2 lines as args, such as an openvpn password file # [[ -f $1 ]] && cat $1 | xargs -n2 command --option # Call command with all lines as args # [[ -f $1 ]] && cat $1 | xargs command --option 

Commentaires

  • a fonctionné comme un charme 🙂
  • +1 adoré, merci

Réponse

La meilleure réponse que jai pour und est:

for i in `cat`; do "$cmd" "$i"; done < $file 

EDIT:

… quatre ans plus tard …

après plusieurs votes négatifs et un peu plus dexpérience, je « recommanderais ce qui suit maintenant:

xargs -l COMMAND < file 

Commentaires

  • Cela invoquera la commande une fois pour chaque word du fichier. De plus, vous devriez toujours citer les références aux variables shell (comme dans do "$cmd" "$i";) sauf si vous avez une raison de ne pas le faire; si le fichier contenait un * en tant que mot à lui seul, votre code exécuterait $cmd *, ce qui, bien sûr, exécuterait la commande avec une liste des fichiers dans le répertoire courant.
  • @ G-Man, sauf dans zsh, le `cat` développerait déjà le * (le $i sans guillemets pourrait encore développer un caractère générique (un deuxième tour) si lexpansion de `cat` en introduit). Dans tous les cas, cette approche est en effet erronée.
  • +1. Cela fonctionnera très bien, si chaque ligne ne contient que lentrée nécessaire à la commande utilisée sans espaces.
  • +1, a aimé la solution xargs
  • Cela fonctionne! (la dernière modification xargs -l COMMAND < file). Merci!

Réponse

 sed "s/"/"\\\\""/g;s/.*/\$* "&"/" <<\FILE |\ sh -s -- command echo --option all of the{&}se li$n\es "are safely shell quoted and handed to command as its last argument following --option, and, here, before that echo FILE 

OUTPUT

--option all of the{&}se li$n\es "are safely shell --option quoted and handed to command as its last argument --option following --option, and, here, before that echo 

Réponse

ed file.txt %g/^/s// / 2,$g/^/-,.j 1s/^/command/ wq chmod 755 file.txt ./file.txt 

Prenez toutes les lignes dun fichier et passez-les comme arguments à une seule commande, cest-à-dire

command line1 line2 line3 .... 

Si vous avez besoin de --option indicateur pour précéder chaque ligne, remplacez la deuxième commande par:

%g/^/s// --option / 

Commentaires

  • Quest-ce que -1 pour en utilisant ed … vraiment?
  • Je ne vous ‘ t contre vous, mais la personne qui l’a fait a probablement eu les raisons suivantes: (1) Ce n’est pas le cas ce que demande la question. Cela appelle la commande une fois avec tout le contenu du fichier sur la ligne de commande; plutôt que une fois par ligne .(2) Cela ne fait rien pour gérer les caractères qui sont spéciaux pour le shell (qui pourraient être dans le fichier); par exemple, ', ", <, >, ;, etc. (3) Cela crée un fichier temporaire inutile. (4) Des choses comme celles-ci se font généralement avec des «documents ici». (5) Vos commandes ed sont maladroites; les deux premières commandes peuvent être réduites à %s/^/ / et %j.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *