primera parametros linea leer funciones fichero ejemplos archivo bash stdin

parametros - leer la primera linea de un archivo bash



¿Cómo leer desde un archivo o stdin en Bash? (13)

En Perl, el siguiente código se leerá desde el archivo especificado en la línea de comando args o desde stdin:

while (<>) { print($_); }

Esto es muy conveniente Solo quiero saber cuál es la forma más sencilla de leer desde un archivo o stdin en bash.


Aquí está la manera más simple:

#!/bin/sh cat -

Uso:

$ echo test | sh my_script.sh test

Para asignar stdin a la variable, puede usar: STDIN=$(cat -) o simplemente STDIN=$(cat) ya que el operador no es necesario (según @ mklement0 comment ).

Para analizar cada línea desde la entrada estándar , pruebe el siguiente script:

#!/bin/bash while IFS= read -r line; do printf ''%s/n'' "$line" done

Para leer desde el archivo o stdin (si el argumento no está presente), puede extenderlo a:

#!/bin/bash file=${1--} # POSIX-compliant; ${1:--} can be used either. while IFS= read -r line; do printf ''%s/n'' "$line" # Or: env POSIXLY_CORRECT=1 echo "$line" done < <(cat -- "$file")

Notas:

- read -r - No trates una barra invertida de ninguna manera especial. Considere que cada barra invertida es parte de la línea de entrada.

- Sin configurar IFS , por defecto las secuencias de espacio y tabulación al principio y al final de las líneas se ignoran (recortan).

- Use printf lugar de echo para evitar imprimir líneas vacías cuando la línea consiste en una sola -e , -n o -E . Sin embargo, hay una solución mediante el uso de env POSIXLY_CORRECT=1 echo "$line" que ejecuta su echo GNU externo que lo admite. Ver: ¿Cómo echo "-e"?

Ver: ¿Cómo leer stdin cuando no se pasan los argumentos? en SE


Con más precisión...

while IFS= read -r line ; do printf "%s/n" "$line" done < file


Creo que esta es la manera directa:

$ cat reader.sh #!/bin/bash while read line; do echo "reading: ${line}" done < /dev/stdin

-

$ cat writer.sh #!/bin/bash for i in {0..5}; do echo "line ${i}" done

-

$ ./writer.sh | ./reader.sh reading: line 0 reading: line 1 reading: line 2 reading: line 3 reading: line 4 reading: line 5


El código ${1:-/dev/stdin} solo comprenderá el primer argumento, entonces, ¿qué tal esto?

ARGS=''$*'' if [ -z "$*" ]; then ARGS=''-'' fi eval "cat -- $ARGS" | while read line do echo "$line" done


El ciclo de Perl en la pregunta se lee de todos los argumentos de nombre de archivo en la línea de comando, o de la entrada estándar si no se especifican archivos. Las respuestas que veo parecen procesar un único archivo o entrada estándar si no hay ningún archivo especificado.

Aunque a menudo se ridiculiza con precisión como UUOC (Uso inútil del cat ), hay momentos en que el cat es la mejor herramienta para el trabajo, y es discutible que este sea uno de ellos:

cat "$@" | while read -r line do echo "$line" done

El único inconveniente de esto es que crea una tubería que se ejecuta en un subconjunto, por lo que las asignaciones variables en el ciclo while no son accesibles fuera de la interconexión. El camino bash es la Sustitución de procesos :

while read -r line do echo "$line" done < <(cat "$@")

Esto deja el bucle while ejecutándose en el shell principal, por lo que las variables establecidas en el bucle son accesibles fuera del bucle.


El comportamiento de Perl, con el código dado en el PO, no puede tomar ninguno o varios argumentos, y si un argumento es un solo guión - esto se entiende como stdin. Además, siempre es posible tener el nombre de archivo con $ARGV . Ninguna de las respuestas dadas hasta ahora realmente imita el comportamiento de Perl en estos aspectos. Aquí hay una posibilidad pura de Bash. El truco es usar el exec apropiadamente.

#!/bin/bash (($#)) || set -- - while (($#)); do { [[ $1 = - ]] || exec < "$1"; } && while read -r; do printf ''%s/n'' "$REPLY" done shift done

El nombre de archivo está disponible en $1 .

Si no se dan argumentos, establecemos artificialmente - como el primer parámetro posicional. Luego hacemos un bucle en los parámetros. Si un parámetro no es - , redirigimos la entrada estándar de nombre de archivo con exec . Si esta redirección tiene éxito, hacemos un bucle con un ciclo while. Estoy usando la variable estándar REPLY , y en este caso no necesita reiniciar IFS . Si desea otro nombre, debe restablecer IFS como tal (a menos que, por supuesto, no lo desee y sepa lo que está haciendo):

while IFS= read -r line; do printf ''%s/n'' "$line" done


La siguiente solución se lee de un archivo si se llama al script con un nombre de archivo como el primer parámetro $1 contrario, desde la entrada estándar.

while read line do echo "$line" done < "${1:-/dev/stdin}"

La sustitución ${1:-...} toma $1 si se define, de lo contrario se utiliza el nombre de archivo de la entrada estándar del proceso propio.


La solución de echo agrega nuevas líneas cada vez que IFS rompe la secuencia de entrada. La respuesta de @ fgm se puede modificar un poco:

cat "${1:-/dev/stdin}" > "${2:-/dev/stdout}"


Lo siguiente funciona con sh estándar (probado con dash en Debian) y es bastante legible, pero eso es una cuestión de gusto:

if [ -n "$1" ]; then cat "$1" else cat fi | commands_and_transformations

Detalles: si el primer parámetro no está vacío, cat ese archivo, de lo contrario, ingrese la entrada estándar. Entonces, la salida de la sentencia if completa es procesada por los commands_and_transformations .


No encuentro ninguna de estas respuestas aceptable. En particular, la respuesta aceptada solo maneja el primer parámetro de línea de comando e ignora el resto. El programa Perl que está tratando de emular maneja todos los parámetros de línea de comando. Entonces la respuesta aceptada ni siquiera responde la pregunta. Otras respuestas usan extensiones de bash, agregan comandos ''cat'' innecesarios, solo funcionan para el caso simple de hacer eco de entrada a salida, o simplemente son innecesariamente complicados.

Sin embargo, tengo que darles un poco de crédito porque me dieron algunas ideas. Aquí está la respuesta completa:

#!/bin/sh if [ $# = 0 ] then DEFAULT_INPUT_FILE=/dev/stdin else DEFAULT_INPUT_FILE= fi # Iterates over all parameters or /dev/stdin for FILE in "$@" $DEFAULT_INPUT_FILE do while IFS= read -r LINE do # Do whatever you want with LINE here. echo $LINE done < "$FILE" done


Por favor intente con el siguiente código:

while IFS= read -r line; do echo "$line" done < file


Qué tal si

for line in `cat`; do something($line); done