¿Por qué este script de shell imprime entradas dos veces?
Esperaba que el script ignorara las entradas después de 5.
Guión:
#! /bin/bash
echo "Enter 5 words : "
read a b c d e
printf "> %s %s %s %s %s <" $a $b $c $d $e
Salida:
user@linux:~$ pico ifs2.sh
user@linux:~$ ./ifs2.sh
Enter 5 words :
1 2 3 4 5
> 1 2 3 4 5 <user@linux:~$ ./ifs2.sh
Enter 5 words :
1 2 3 4 5 6
> 1 2 3 4 5 <> 6 <user@linux:~$ ./ifs2.sh
Enter 5 words :
1 2 3 4 5 6 7 8 9 0
> 1 2 3 4 5 <> 6 7 8 9 0 <user@linux:~$
Y, el siguiente script funciona sin importar lo establecido en $ IFS. ¿Por qué?
#! /bin/bash
old="$IFS"
IFS=":"
echo "IFS = $IFS"
echo "Enter 5 words : "
read a b c d e
printf "> %s %s %s %s %s <" $a $b $c $d $e
IFS="$old"
Salida:
user@linux:~$ ./ifs2.sh
IFS = :
Enter 5 words :
1 2 3 4 5
> 1 2 3 4 5 <user@linux:~$ ./ifs2.sh
IFS = :
Enter 5 words :
1 2 3 4 5
> 1 2 3 4 5 <user@linux:~$ ./ifs2.sh
IFS = :
Enter 5 words :
1:2:3:4:5
> 1 2 3 4 5 <user@linux:~$
shell-script
mikeserv
fuente
fuente
printf
en cualquier momento con el\c
escape asociado con un%b
especificador de formato. Así como:printf %s%\ d%b thing 3 "${var+\cquit printing if set}\nelse do a newline" and 0 keep\ going.
Respuestas:
Tienes tres problemas:
read
, si hay menos nombres de variables que campos en la entrada, la última var estará vinculada a todos los campos restantes en la línea, con delimitadores. Eso significa que$e
entra5 6
en su primer ejemplo inesperado.$a
...$e
no están entre comillas, sus valores sufren división de campo . Si$e
contiene "5 6
", se expande en dos argumentos para el comando.printf
consume todos sus argumentos, usando tantos argumentos a la vez como%
sustituciones, repetidamente. Esto está enterrado en la documentación como:En otras palabras, si hay argumentos no utilizados, comienza de nuevo y los procesa desde el principio, incluida toda la cadena de formato. Esto es útil cuando desea formatear una matriz completa, por ejemplo:
Su
printf
comando obtiene un argumento de cada uno de$a
...$d
y luego, sin embargo, quedan muchos$e
. Cuando$e
es "5 6
",printf
tiene dos vueltas, la segunda solo6
formateando. Cuando es5 6 7 8 9 10
tiene la gama completa de sustituciones para la segunda impresión.Puede evitar todo esto agregando un campo ficticio adicional
read
y citando las sustituciones de sus parámetros (que siempre es una buena idea):Esto le dará:
dummy
obtiene todos los campos adicionales yprintf
solo obtiene los cinco argumentos que esperaba.Su segunda pregunta editada tiene una respuesta similar: solo
a
obtiene un valor cuandoIFS
no tiene un espacio. Eso significa$b
...$e
expandirse a nada, por lo queprintf
solo obtiene un argumento único. Sus espacios de la cadena de formato se imprimen, sin nada sustituido entre ellos ("como si se suministrara un argumento de cadena nula").fuente
a
tiene el valor1 2 3 4 5
como una sola cadena y se sustituye de una vez.imprimirá
huellas dactilares
printf
se come todos los argumentos para satisfacer su cadena de formato y luego se repite hasta que se procesen todos los argumentos.El segundo script funciona porque solo
$a
se asigna y, por lo tanto, el comando no se desborda en iteraciones adicionales (solo hay una iteración).Este comportamiento está documentado en el texto provisto con
help printf
:y tiene el mandato de http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html
fuente