Por que esse script de shell imprime as entradas duas vezes?
Eu esperava que o script ignorasse as entradas após 5.
Roteiro:
#! /bin/bash
echo "Enter 5 words : "
read a b c d e
printf "> %s %s %s %s %s <" $a $b $c $d $e
Resultado:
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:~$
E, o script a seguir funciona, independentemente do que estiver definido como $ 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"
Resultado:
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
fonte
fonte
printf
a qualquer momento com o\c
escape associado a um%b
especificador de formato. Como:printf %s%\ d%b thing 3 "${var+\cquit printing if set}\nelse do a newline" and 0 keep\ going.
Respostas:
Você tem três problemas:
read
, se houver menos nomes de variáveis que campos na entrada, a última var será vinculada a todos os campos restantes na linha, com delimitadores. Isso significa que$e
entra5 6
no seu primeiro exemplo inesperado.$a
..$e
não estão entre aspas, seus valores passam por uma divisão de campo . Se$e
contém "5 6
", ele se expande em dois argumentos para o comando.printf
consome todos os seus argumentos, usando o mesmo número de argumentos ao mesmo tempo que houver%
substituições, repetidamente. Isso está oculto na documentação como:Em outras palavras, se houver argumentos não utilizados, ele recomeça e os processa também desde o início, incluindo toda a cadeia de formato. Isso é útil quando você deseja formatar uma matriz inteira, diga:
Seu
printf
comando obtém um argumento de cada um de$a
...$d
e, no entanto, muitos são os que restam$e
. Quando$e
é "5 6
",printf
tem duas voltas, a segunda apenas começando6
a formatar. Quando é5 6 7 8 9 10
, possui toda a gama de substituições para a segunda impressão.Você pode evitar tudo isso adicionando um campo fictício extra a
read
e citando suas substituições de parâmetro (o que é sempre uma boa idéia):Isso dará:
dummy
obtém todos os campos extras eprintf
somente os cinco argumentos que você esperava.Sua segunda pergunta editada tem uma resposta semelhante: só
a
obtém um valor quandoIFS
não há espaço. Isso significa$b
...$e
expandir para nada, entãoprintf
apenas recebe um único argumento. Seus espaços da string de formato são impressos, sem nada substituído entre eles ("como se um argumento de string nulo fosse fornecido").fonte
a
tem o valor1 2 3 4 5
como uma única sequência e é substituído de uma só vez.irá imprimir
impressões
printf
utiliza todos os argumentos para satisfazer sua cadeia de formatação e depois se repete até que todos os argumentos sejam processados.O segundo script funciona porque somente
$a
é atribuído e, portanto, o comando não transborda para iterações adicionais (há apenas uma iteração).Esse comportamento está documentado no texto fornecido com
help printf
:e é mandatado por http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html
fonte