¿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

printfen cualquier momento con el\cescape asociado con un%bespecificador 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$eentra5 6en su primer ejemplo inesperado.$a...$eno están entre comillas, sus valores sufren división de campo . Si$econtiene "5 6", se expande en dos argumentos para el comando.printfconsume 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
printfcomando obtiene un argumento de cada uno de$a...$dy luego, sin embargo, quedan muchos$e. Cuando$ees "5 6",printftiene dos vueltas, la segunda solo6formateando. Cuando es5 6 7 8 9 10tiene la gama completa de sustituciones para la segunda impresión.Puede evitar todo esto agregando un campo ficticio adicional
ready citando las sustituciones de sus parámetros (que siempre es una buena idea):Esto le dará:
dummyobtiene todos los campos adicionales yprintfsolo obtiene los cinco argumentos que esperaba.Su segunda pregunta editada tiene una respuesta similar: solo
aobtiene un valor cuandoIFSno tiene un espacio. Eso significa$b...$eexpandirse a nada, por lo queprintfsolo 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
atiene el valor1 2 3 4 5como una sola cadena y se sustituye de una vez.imprimirá
huellas dactilares
printfse 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
$ase 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