Bash Read: Lectura de la lista separada por comas, se pierde el último elemento


8

El resultado del comando a continuación es extraño para mí. ¿Por qué no me devuelve el elemento 5?

$ echo '0,1,2,3,4,5' | while read -d, i; do echo $i; done
0
1
2
3
4

Esperaría que '5' sea devuelto también. Correr GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu). Agregar una coma funciona, pero mis datos de entrada no tienen una coma. ¿Me estoy perdiendo de algo?

Respuestas:


12

Con read, -dse usa para terminar las líneas de entrada (es decir, no para separar las líneas de entrada). Su última "línea" no contiene ningún terminador, por lo que readdevuelve falso en EOF y el ciclo sale (aunque se haya leído el valor final).

echo '0,1,2,3,4,5' | { while read -d, i; do echo "$i"; done; echo "last value=$i"; }

(Incluso con -d, readtambién usa $IFS, absorber espacios en blanco, incluido el seguimiento \ndel valor final que aparecería usando otros métodos como readarray)

Las preguntas frecuentes de Bash discuten esto y cómo manejar varios casos similares:


8
Supongo que uno podría hacer read -d, i || [[ -n $i ]]a la ¿Qué while read -r line || [[ -n $line ]]significa?
Steeldriver

8

Como dicen otras respuestas, -des un carácter de fin de línea, no un separador de campo. Tu puedes hacer

IFS=, read -a fields <<< "1,2,3,4,5"
for i in "${fields[@]}"; do echo "$i"; done

5

Del hombre:

-d delim

El primer carácter de delim se usa para terminar la línea de entrada, en lugar de la nueva línea.

Su elemento 5 no tiene un delimitador (coma), por lo que no se leerá.


Entonces, ¿la mejor solución es poner otra coma después de la entrada?
Karlo

3
La mejor solución podría ser procesar datos con algo que no sea un shell . Como los que respondieron aquí han abordado la pregunta actual, puede considerar una pregunta separada que demuestre su objetivo más amplio.
Jeff Schaller

3

Lo que está viendo es el mismo comportamiento (y por la misma razón) que ¿Por qué este bucle 'while' no reconoce la última línea?

Como en ese caso, puede modificar el comportamiento agregando una prueba adicional a la condición de terminación del bucle, de la siguiente manera

while read -d, i || [[ -n $i ]]; do ...

Ex.

$ echo '0,1,2,3,4,5' | while read -d, i || [[ -n $i ]]; do echo $i; done
0
1
2
3
4
5
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.