O bash tem diferentes regras de cotação fracas para variáveis especiais?

6

Eu não acho que entendo completamente as nuances da citação no bash.

Eu tenho um script, foo.sh , que simplesmente exibe argumentos numerados.

#!/bin/bash

i=1
while [ $i -le $# ] ; do
    v=$(eval "echo \$$i")
    echo "$i: $v"
    i=$((i + 1))
done

Você pode usá-lo assim:

me@localhost] ./foo.sh a b c
1: a
2: b
3: c

Se eu definir a variável args como um valor contendo um espaço (como "super nintendo" ), posso usar sem cotação para que o bash trate como dois argumentos:

me@localhost] args="super nintendo" ; ./foo.sh $args
1: super
2: nintendo

Ou eu posso usar quoting fraco (aspas duplas) para que o bash o trate como um único argumento, mas expandindo a variável para o valor real:

me@localhost] args="super nintendo" ; ./foo.sh "$args"
1: super nintendo

Ou eu posso usar strong-quoting (aspas simples) para tratá-lo literalmente como digitado:

me@localhost] args="super nintendo" ; ./foo.sh '$args'
1: $args

No entanto, a cotação fraca da variável especial $@ parece agir como se não houvesse cotação. Por exemplo, bar.sh abaixo das chamadas foo.sh duas vezes, uma vez com cotação fraca e uma vez sem cotação.

#!/bin/bash

./foo.sh "$@"
./foo.sh $@

Chamar isso com ./bar.sh a b c produz saída idêntica para as duas chamadas para foo.sh :

1: a
2: b
3: c
1: a
2: b
3: c

O que eu esperava ver era o seguinte:

1: a b c
1: a
2: b
3: c

O que eu estou perdendo citando no bash aqui?

    
por magnus 30.01.2017 / 00:27

1 resposta

12

Isso porque $@ é uma matriz e as citações de matrizes têm regras diferentes:

  • "${array[@]}" ou "$@" se expande para membros da matriz
  • "${array[*]}" ou "$*" expande para elementos da matriz unidos pelo primeiro caractere da variável $IFS .

Experimente vários argumentos, alguns deles contendo espaços:

./foo.sh 'one two' three
    
por 30.01.2017 / 00:31