problema de readarray (o tubería)

Me quedé con un comportamiento extraño del comando readarray.

El man bash dice:

readarray Read lines from the standard input into the indexed array variable array 

pero estos scripts no funcionan (la matriz está vacía):

unset arr; (echo a; echo b; echo c) | readarray arr; echo ${#arr[@]} unset arr; cat /etc/passwd | readarray arr; echo ${#arr[@]} 

Y estos funcionan:

unset arr; readarray arr < /etc/passwd ; echo ${#arr[@]} unset arr; mkfifo /tmp/fifo; (echo a; echo b; echo c) > /tmp/fifo & mapfile arr < /tmp/fifo ; echo ${#arr[@]} 

¿Qué pasa con la tubería?

Respuesta

Tal vez intente:

unset arr printf %s\\n a b c | { readarray arr echo ${#arr[@]} } 

Espero que funcione , pero en el momento en que sales de ese último contexto { shell ; } al final del | pipeline allí perderá el valor de su variable. Esto se debe a que cada uno de los | procesos | separados dentro de una | se ejecuta en una ( subshell ). Así que lo tuyo no funciona por la misma razón:

( arr=( a b c ) ) ; echo ${arr[@]} 

… no «t – el valor de la variable se estableció en un diferente proceso de shell que en el que lo invocas.

Responder

Para garantizar la se ejecuta en el shell actual; utilice la sustitución del proceso en lugar de la canalización:

readarray -t arr < <( echo a; echo b; echo c ) 

o (si bash 4.2 o posterior) use la lastpipe opción de shell:

shopt -s lastpipe ( echo a; echo b; echo c ) | readarray -t arr 

Comentarios

  • Genial. Esto funciona, pero ¿qué es exactamente la sustitución de procesos? ¿Y qué significa tener < < 2 flechas?
  • Consulte la bash página de manual. En resumen, es la sintaxis ' s para tratar una canalización como un descriptor de archivo. < <(...) significa redirigir la entrada (la primera <) de la salida del comando dentro de <(...). De manera similar, > >(...) pasaría la salida estándar a la entrada estándar de la canalización dentro de >(...). No ' no es necesario que utilice la redirección con sustitución de procesos. cat <( echo a b c ) también funciona.
  • Ambas opciones producen un resultado no deseado para mí, donde cada elemento de la matriz retiene los finales de línea al final de cada cadena. Mientras que la respuesta de smac89 no tiene este problema.
  • Los finales de línea se pueden quitar usando readarray -t arr. De man bash: -t Remove a trailing newline from each line read.
  • Yo ' estoy usando bash 5.0.17 y esto no ' me funciona. ' incluso he comprobado BASHOPTS y contiene lastpipe, pero cat myfile.txt | readarray -t arr da un arr vacío, pero readarray -t arr < <(cat myfile.txt) funciona correctamente.

Respuesta

readarray también puede leer desde stdin, por lo que:

readarray arr <<< "$(echo a; echo b; echo c)"; echo ${#arr[@]} 

Deja una respuesta

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