Pourquoi ce script shell imprime-t-il deux fois les entrées?
Je m'attendais à ce que le script ignore les entrées après 5.
Scénario:
#! /bin/bash
echo "Enter 5 words : "
read a b c d e
printf "> %s %s %s %s %s <" $a $b $c $d $e
Production:
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:~$
Et, le script suivant fonctionne quel que soit le paramètre défini sur $ IFS. Pourquoi?
#! /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"
Production:
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
la source
la source
printf
à tout moment avec l'\c
échappement associé à un%b
spécificateur de format. Comme:printf %s%\ d%b thing 3 "${var+\cquit printing if set}\nelse do a newline" and 0 keep\ going.
Réponses:
Vous avez trois problèmes:
read
, s'il y a moins de noms de variables que de champs dans l'entrée, la dernière var sera liée à tous les champs restants de la ligne, avec des délimiteurs. Cela signifie que cela$e
entre5 6
dans votre premier exemple inattendu.$a
.. ne$e
sont pas cités, leurs valeurs subissent une division de champ . Si$e
contient "5 6
", il se développe en deux arguments à la commande.printf
consomme tous ses arguments, en utilisant autant d'arguments à la fois qu'il y a de%
substitutions, à plusieurs reprises. Ceci est enterré dans la documentation comme:En d'autres termes, s'il y a des arguments inutilisés, il recommence et les traite aussi depuis le début, y compris la chaîne de formatage entière. Ceci est utile lorsque vous souhaitez formater un tableau entier, par exemple:
Votre
printf
commande obtient un argument de chacun de$a
..$d
, et ensuite, il en reste beaucoup$e
. Quand$e
est "5 6
", il y enprintf
a deux, le second se met simplement6
au format. Quand c'est,5 6 7 8 9 10
il a la gamme complète de substitutions pour la deuxième impression.Vous pouvez éviter tout cela en ajoutant un champ factice supplémentaire à
read
, et en citant vos substitutions de paramètres (ce qui est toujours une bonne idée):Cela donnera:
dummy
obtient tous les champs supplémentaires etprintf
n'obtient que les cinq arguments que vous attendiez.Votre deuxième question modifiée a une réponse similaire:
a
n'obtient une valeur que si elleIFS
n'a pas d'espace. Cela signifie que$b
…$e
ne rien développer, doncprintf
n'obtient qu'un seul argument. Vos espaces de la chaîne de format sont imprimés, sans rien remplacer entre eux ("comme si un argument de chaîne nulle était fourni").la source
a
a la valeur1 2 3 4 5
comme une chaîne unique et elle est remplacée d'un seul coup.imprimera
impressions
printf
mange tous les arguments pour satisfaire sa chaîne de format, puis se répète jusqu'à ce que tous les arguments soient traités.Le deuxième script fonctionne car seul
$a
est jamais affecté à et donc la commande ne déborde pas dans des itérations supplémentaires (il n'y a qu'une seule itération).Ce comportement est documenté dans le texte fourni avec
help printf
:et est mandaté par http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html
la source