¿Cómo analizar cada línea de un archivo de texto como argumento de un comando?

Estoy buscando escribir un script que tome un .txt nombre de archivo como argumento, lee la línea del archivo por línea y pasa cada línea a un comando. Por ejemplo, ejecuta command --option "LINE 1", luego command --option "LINE 2", etc. La salida del comando está escrito en otro archivo. ¿Cómo puedo hacerlo? No sé por dónde empezar.

Respuesta

Use while read bucle:

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

Otra es redirigir la salida por bloque:

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

Lo último es abrir el archivo:

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 uno de los comandos lee input, sería bueno idea de usar otro fd para la entrada para que los comandos «no se lo coman (aquí asumiendo ksh, zsh o bash para -u 3, use <&3 en su lugar portátil):

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

Aleta Aliado para aceptar argumentos, puede hacer:

#!/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" 

Cuál podría ejecutarse como:

bash script.sh file another_file 

Idea adicional. Con bash, use readarray:

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

Nota: IFS= se puede omitir si no le importa que los valores de línea se eliminen de los espacios iniciales y finales.

Respuesta

Otra opción es xargs.

Con GNU xargs:

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

{} es el marcador de posición para la línea de texto.

Otro xargs generalmente no» tienen -a, -d, pero algunos tienen -0 para entrada delimitada por NUL. Con ellos, puede hacer:

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

En sistemas compatibles con Unix (-I es opcional en POSIX y solo requerido para los sistemas que cumplen con UNIX), necesitará preprocesar la entrada para citar las líneas en el formato esperado por xargs:

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

Sin embargo, tenga en cuenta que algunas xargs implementaciones tienen un límite muy bajo en el tamaño máximo del argumento (255 en Solaris, por ejemplo, el mínimo permitido por la especificación de Unix).

Comentarios

  • reducible a <file xargs -L 1 -I{} command --option {} other args
  • @iruvar, no, eso procesaría comillas y eliminaría algunos espacios en blanco.

Responder

Mantener la precisión a la pregunta:

#!/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 

Comentarios

  • funcionó a la perfección 🙂
  • +1 me encantó esto, gracias

Responder

La mejor respuesta para und es:

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

EDITAR:

… cuatro años después …

después de varios votos negativos y algo más de experiencia, recomendaría lo siguiente ahora:

xargs -l COMMAND < file 

Comentarios

  • Esto invocará el comando una vez por cada word en el archivo. Además, siempre debe citar referencias a variables de shell (como en do "$cmd" "$i";) a menos que tenga una razón para no hacerlo; si el archivo contiene un * como una palabra por sí mismo, su código ejecutará $cmd *, que, por supuesto, ejecutará el comando con una lista de los archivos en el directorio actual.
  • @ G-Man, excepto en zsh, el `cat` ya expandiría el * (el $i sin comillas aún podría expandir algún comodín (una segunda ronda) si la expansión de `cat` presenta algunos). En cualquier caso, ese enfoque es incorrecto.
  • +1. Esto funcionará bien, si cada línea contiene solo la entrada necesaria para el comando que se usa sin espacios.
  • +1, me gustó la solución xargs
  • ¡Esto está funcionando! (la edición posterior xargs -l COMMAND < file). ¡Gracias!

Respuesta

 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 

SALIDA

--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 

Responder

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

Tome todas las líneas de un archivo y pasarlas como argumentos a un solo comando, es decir,

command line1 line2 line3 .... 

Si necesita --option bandera para preceder cada línea cambie el segundo comando a:

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

Comentarios

  • ¿Para qué -1 usando ed … ¿de verdad?
  • Yo no ‘ t voté en contra de ti, pero la persona que lo hizo probablemente tuvo estas razones: (1) Esto no lo que pide la pregunta. Esto invoca el comando una vez con todo el contenido del archivo en la línea de comando; en lugar de una vez por línea .(2) Esto no hace nada para manejar caracteres que son especiales para el shell (que podrían estar en el archivo); Por ejemplo, ', ", <, >, ;, etc. (3) Esto crea un archivo temporal innecesario. (4) Cosas como esta generalmente se hacen con «aquí documentos». (5) Tus ed comandos son torpes; los dos primeros comandos se pueden reducir a %s/^/ / y %j.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *