A expansão de variáveis funciona de forma diferente dependendo do contexto em que a variável está?

0

Digamos que fiz o seguinte:

IFS=,
x="hello,hi,world"
y=$x

y terá a string hello hi world , então é como y=$x foi substituído por:

y="hello hi world"

Agora diga que eu tenho o seguinte script:

IFS=,
x="hello,hi,world"
if [ $x = "hello hi world" ]
then
    echo "equal"
fi

Ao executar o script acima, recebo o seguinte erro:

test.sh: line 3: [: too many arguments

Suponho que recebi este erro porque a instrução if [ $x = "hello hi world" ] foi substituída por if [ hello hi world = "hello hi world" ] e não por if [ "hello hi world" = "hello hi world" ] na execução.

Portanto, isso significa que a variável $x foi expandida de duas maneiras diferentes, dependendo do contexto em que estava (uma vez, foi expandida com aspas duplas e outra vez foi expandida sem aspas duplas).

Estou correto?

    
por user267935 04.01.2018 / 21:17

4 respostas

4

y will have the string hello hi world

Não, não vai. Expansões em atribuições de variáveis não estão sujeitas a divisão de palavras ou globalização de nomes de arquivos. (Em certo sentido, eles sempre agem como se estivessem citando duas vezes.) Veja: Quando é cotação dupla é necessária?

$ IFS=,
$ x="hello,hi,world"; y=$x
$ echo "$y"
hello,hi,world

I assume that I got this error because the statement if [ $x = "hello hi world" ] was replaced by if [ hello hi world = "hello hi world" ]

Sim, mais ou menos. Não é uma substituição baseada em texto, mas como $x não foi citado aqui, ela passa pela divisão de palavras e o comando [ vê seis argumentos distintos ( hello , hi , world , = , hello hi world e ] ), não os quatro esperados.

    
por 04.01.2018 / 21:58
0

As variáveis realmente se comportam de maneira diferente em relação às citações, se forem usadas em atribuições. Em

y=$x

nenhuma divisão de palavras é executada, ou seja, é equivalente a

y="$x"

Mas em uma expansão de parâmetro normal como

if [ $x =

faz diferença se há cotações. BTW: Com aspas $x não teria sido expandido para "hello hi world" mas "hello,hi,world" .

    
por 04.01.2018 / 22:00
0

A divisão de palavras não ocorre durante a atribuição de variáveis, portanto, y contém hello,hi,world . No entanto, a divisão de palavras ocorre dentro de [] e, como você define IFS=, , ela é expandida para hello hi world como palavras separadas.

O problema é que [ espera um número específico de argumentos e está lhe dizendo que recebeu muitos por causa da divisão de palavras. Como você marcou isso com bash , você pode usar seu comando superior [[ ]] para desabilitar a divisão de palavras e não obterá o erro.

Se você realmente quiser fazer a divisão de palavras em x , poderá fazer assim: y="$(IFS=','; echo $x)" . Isso atribuirá hello hi world como uma palavra a y .

    
por 04.01.2018 / 22:11
0

Você está citando problemas:

  1. Expansão variável:

    y will have the string hello hi world

    Não, não vai. Mas um eco sem aspas imprime esse valor:

    $ IFS=,
    $ x="hello,hi,world"
    $ y=$x
    $ echo $y
    hello hi world
    

    Sim, o caractere IFS ( , ) divide a expansão da variável e o echo coloca um espaço entre os argumentos, veja isto para ver em detalhes:

    $ printf '<%s>\n' $y
    <hello>
    <hi>
    <world>
    

    No entanto, uma expansão entre aspas não será alterada pelo IFS nem dividida:

    $ echo "$y"
    hello,hi,world
    $ printf '<%s>\n' "$y"
    <hello,hi,world>
    
  2. Linha de teste

    [ $x = "hello hi world" ]
    

    O mesmo problema de cotação acontece aqui, a variável é expandida e dividida em palavras. A linha se torna:

    [ hello hi world = "hello hi world" ]
    

    Os três argumentos "olá", "olá" e "mundo" não podem ser analisados em uma construção de teste correta.

    Isso, no entanto, faz:

    $ y=hello,=,world,-o,hello
    $ [ $y = "hello" ] && echo yes || echo no
    yes
    

    porque o que foi executado foi:

    [ hello = world -o hello = "hello" ] && echo yes || echo no
    

    As citações evitam a divisão:

    $ y=hello,hi,world
    $ [ "$y" = "hello,hi,world" ] && echo yes || echo no
    yes
    

    Como o uso da construção [[ também evita a divisão:

    $ y=hello,hi,world
    $ [[ $y == "hello,hi,world" ]] && echo yes || echo no
    yes
    
  3. Sua pergunta:

    Am I correct?

    Não, cada vez que a variável é expandida da mesma maneira.

TL; DR

Cite suas expansões.

    
por 05.01.2018 / 02:25

Tags