¿Cómo itero a través de cada línea de un archivo de texto con Bash ?
Con este script:
echo "Start!"
for p in (peptides.txt)
do
echo "${p}"
done
Me sale este resultado en la pantalla:
Start!
./runPep.sh: line 3: syntax error near unexpected token `('
./runPep.sh: line 3: `for p in (peptides.txt)'
(Más tarde, quiero hacer algo más complicado $pque simplemente enviarlo a la pantalla).
La variable de entorno SHELL es (de env):
SHELL=/bin/bash
/bin/bash --version salida:
GNU bash, version 3.1.17(1)-release (x86_64-suse-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.
cat /proc/version salida:
Linux version 2.6.18.2-34-default (geeko@buildhost) (gcc version 4.1.2 20061115 (prerelease) (SUSE Linux)) #1 SMP Mon Nov 27 11:46:27 UTC 2006
El archivo peptides.txt contiene:
RKEKNVQ
IPKKLLQK
QYFHQLEKMNVK
IPKKLLQK
GDLSTALEVAIDCYEK
QYFHQLEKMNVKIPENIYR
RKEKNVQ
VLAKHGKLQDAIN
ILGFMK
LEDVALQILL

Respuestas:
Una forma de hacerlo es:
Como se señaló en los comentarios, esto tiene los efectos secundarios de recortar los espacios en blanco iniciales, interpretar las secuencias de barra invertida y omitir la última línea si falta un salto de línea de terminación. Si estas son preocupaciones, puede hacer:
Excepcionalmente, si el cuerpo del bucle puede leer desde la entrada estándar , puede abrir el archivo usando un descriptor de archivo diferente:
Aquí, 10 es solo un número arbitrario (diferente de 0, 1, 2).
fuente
while read p || [[ -n $p ]]; do ...y la variante de una línea:
Estas opciones omitirán la última línea del archivo si no hay avance de línea final.
Puede evitar esto de la siguiente manera:
fuente
Opción 1a: Bucle While: línea única a la vez: redirección de entrada
Opción 1b: Bucle While: línea única a la vez:
abra el archivo, lea desde un descriptor de archivo (en este caso, el descriptor de archivo # 4).
fuente
done < $filenamepordone 4<$filename(que es útil si desea leer el nombre del archivo de un parámetro de comando, en cuyo caso puede simplemente reemplazarlo$filenamepor$1)tail -n +2 myfile.txt | grep 'somepattern' | cut -f3, mientras ejecuto comandos ssh dentro del ciclo (consume stdin); La opción 2 aquí parece ser la única manera?Esto no es mejor que otras respuestas, pero es una forma más de hacer el trabajo en un archivo sin espacios (ver comentarios). Me parece que a menudo necesito frases para buscar en las listas de los archivos de texto sin el paso adicional de usar archivos de script separados.
Este formato me permite ponerlo todo en una línea de comandos. Cambie la porción "echo $ word" a lo que quiera y puede emitir múltiples comandos separados por punto y coma. El siguiente ejemplo utiliza los contenidos del archivo como argumentos en otros dos scripts que puede haber escrito.
O si tiene la intención de usar esto como un editor de flujo (aprender sed) puede volcar la salida a otro archivo de la siguiente manera.
Los he usado como se escribió anteriormente porque he usado archivos de texto donde los he creado con una palabra por línea. (Ver comentarios) Si tiene espacios en los que no desea dividir sus palabras / líneas, se vuelve un poco más feo, pero el mismo comando aún funciona de la siguiente manera:
Esto solo le dice al shell que se divida solo en nuevas líneas, no en espacios, luego regresa el entorno a lo que era anteriormente. En este punto, es posible que desee considerar poner todo en un script de shell en lugar de exprimirlo todo en una sola línea.
¡La mejor de las suertes!
fuente
forhace que los tokens / líneas de entrada estén sujetos a expansiones de shell, lo que generalmente no es deseable; intente esto:for l in $(echo '* b c'); do echo "[$l]"; donecomo verá, el*- aunque originalmente era un literal citado - se expande a los archivos en el directorio actual.foriterar líneas de archivo es una mala idea. Además, el aspecto de expansión mencionado por @ mklement0 (a pesar de que eso probablemente se puede eludir al incluir comillas escapadas, lo que nuevamente hace que las cosas sean más complejas y menos legibles).Algunas cosas más no cubiertas por otras respuestas:
Leer desde un archivo delimitado
Lectura de la salida de otro comando, usando la sustitución del proceso
Este enfoque es mejor que
command ... | while read -r line; do ...porque el ciclo while aquí se ejecuta en el shell actual en lugar de un subshell como en el caso de este último. Ver la publicación relacionada No se recuerda una variable modificada dentro de un ciclo while .Lectura de una entrada delimitada nula, por ejemplo
find ... -print0Lectura relacionada: BashFAQ / 020 - ¿Cómo puedo encontrar y manejar con seguridad los nombres de archivo que contienen líneas nuevas, espacios o ambos?
Leer desde más de un archivo a la vez
Basado en la respuesta de @ chepner aquí :
-ues una extensión bash. Por compatibilidad POSIX, cada llamada se vería algo asíread -r X <&3.Lectura de un archivo completo en una matriz (versiones Bash anteriores a la 4)
Si el archivo termina con una línea incompleta (falta una nueva línea al final), entonces:
Lectura de un archivo completo en una matriz (versiones Bash 4x y posteriores)
o
Y entonces
Más acerca de los comandos
readyreadarraycomandos integrados de shell - GNUMás sobre
IFS- WikipediaArtículos Relacionados:
fuente
command < input_filename.txtsiempre puede hacerinput_generating_command | commandocommand < <(input_generating_command)Use un ciclo while, como este:
Notas:
Si no configura
IFScorrectamente, perderá la sangría.Casi siempre debe usar la opción -r con lectura.
No lea líneas con
forfuente
-ropción?Note #2es un enlace donde se describe en detalle ...-uopción, ¿estás hablando de otro ejemplo-u?Supongamos que tiene este archivo:
Hay cuatro elementos que alterarán el significado de la salida del archivo leída por muchas soluciones de Bash:
Si desea que el archivo de texto línea por línea incluya líneas en blanco y líneas de terminación sin CR, debe usar un bucle while y debe tener una prueba alternativa para la línea final.
Estos son los métodos que pueden cambiar el archivo (en comparación con lo que
catdevuelve):1) Pierda la última línea y los espacios iniciales y finales:
(Si lo hace
while IFS= read -r p; do printf "%s\n" "'$p'"; done </tmp/test.txt, conserva los espacios iniciales y finales pero aún pierde la última línea si no termina con CR)2) El uso de la sustitución de procesos con
catwill lee todo el archivo de una vez y pierde el significado de las líneas individuales:(Si se quita la
"de$(cat /tmp/test.txt)leer el archivo de la palabra por palabra en lugar de un solo trago. También probablemente no lo que se pretende ...)La forma más sólida y sencilla de leer un archivo línea por línea y preservar todo el espaciado es:
Si desea eliminar los espacios iniciales y comerciales, elimine la
IFS=parte:(Un archivo de texto sin una terminación
\n, aunque bastante común, se considera roto bajo POSIX. Si puede contar con el seguimiento\nno necesita|| [[ -n $line ]]en elwhilebucle).Más en las preguntas frecuentes de BASH
fuente
Si no desea que su lectura se rompa por el carácter de nueva línea, use -
Luego ejecute el script con el nombre del archivo como parámetro.
fuente
fuente
Aquí está mi ejemplo de la vida real: cómo hacer un bucle en las líneas de otra salida del programa, verificar las subcadenas, descartar comillas dobles de la variable, usar esa variable fuera del bucle. Supongo que muchos hacen estas preguntas tarde o temprano.
Declarar variable fuera del ciclo, establecer el valor y usarlo fuera del ciclo requiere la sintaxis <<< "$ (...)" . La aplicación debe ejecutarse dentro de un contexto de la consola actual. Las comillas alrededor del comando mantienen nuevas líneas de flujo de salida.
La coincidencia de bucle para las subcadenas lee el nombre = par de valores , divide la parte derecha del último = carácter, suelta la primera comilla, suelta la última comilla, tenemos un valor limpio para usar en otro lugar.
fuente
Esto llega bastante tarde, pero con la idea de que puede ayudar a alguien, agrego la respuesta. Además, esta puede no ser la mejor manera.
headEl comando se puede usar con-nargumentos para leer n líneas desde el inicio del archivo y del mismo modotailse puede usar el comando para leer desde abajo. Ahora, para obtener la enésima línea del archivo, encabezamos n líneas , canalizamos los datos para seguir solo 1 línea de los datos canalizados.fuente
sedohead+tailes increíblemente ineficiente, y por supuesto plantea la pregunta de por qué no simplemente usa una de las otras soluciones aquí. Si necesita saber el número de línea, agregue un contador a suwhile read -rciclo o usenl -bapara agregar un prefijo de número de línea a cada línea antes del ciclo.Me gusta usar en
xargslugar dewhile.xargses potente y amigable con la línea de comandoscat peptides.txt | xargs -I % sh -c "echo %"Con
xargs, también puede agregar verbosidad-ty validación con-pfuente
@ Peter: Esto podría funcionar para usted
Esto devolvería la salida
fuente