Por que o curinga asterisco (*) não é avaliado nesses dois casos?

0

Se eu tiver este comando:

expr 2 * 4

Ele não funcionará, porque o curinga * será avaliado e, por isso, tenho de escapar dele:

expr 2 \* 4

Mas se eu tiver os dois casos a seguir:

let var1=2*4

var2=$((2*4))

Em seguida, o curinga * não será avaliado e, portanto, não há necessidade de escapar dele.

Por que o curinga * não foi avaliado nos dois casos acima? meu palpite é que bash simplesmente não o avalia quando usar let e $(()) .

Se este for o caso, existem outras situações em que os curingas não são avaliados?

    
por user267498 26.12.2017 / 01:42

3 respostas

1

Em var2=2*4 , devido a espaços (metacaracteres), e que não há arquivo começando com 2 , alguns caracteres e 4 no pwd.

A linha é dividida em tokens usando espaços como delimitadores.

Isso não tem espaços (e após o = é considerado citado):

$ var1=2*4

Mas isso acontece:

$ echo 2 * 4    

E o * se torna um token e é expandido (como uma expansão de nome de arquivo).

Para evitar o efeito especial de * use quoting:

$ expr 2 \* 4
8
$ expr 2 "*" 4
8
$ expr 2 '*' 4
8

No entanto, isso se expande:

$ touch 2good4
$ echo 2*4
2good4

Em echo $((2*4)) , o que está dentro de uma construção $((…)) é interpretado como uma expansão aritmética. qualquer um desses itens fará o mesmo (mesmo com os espaços):

$ echo $((2*4))
8
$ echo $(( 2 * 4 ))
8
$ echo $((    2   *    4    ))
8
    
por 26.12.2017 / 02:41
1

O comportamento que você vê é explicado aqui para globbing e aqui para expansão e a página man let para a especificação de parâmetro que o bash sabe dar para 'let'

Quando o bash vê * por conta própria, ele executa a expansão do nome do caminho exceto onde a expansão retorna um resultado nulo, caso em que retorna a string literal.

echo 2 * 4     #echo 2, the contents of the pwd and then 4

Se * for precedido por um marcador que diga para usar uma forma de diferença ou expansão (matemática / comando / parâmetro ou nenhuma expansão), então ele usa o método relevante. Então

let var1=2*4   #pass the **arithmetic** argument var1=2*4 to the let command because bash knows let takes special characters (% * etc) as arguments

var2=$((2*4))  #bash parses the string as far as $ and sees an instruction to expand
               #bash then sees (( the which specifies arithmetic expansion specifies

e como você disse

echo 2 \* 4   #perform no expansion
    
por 26.12.2017 / 05:34
0

Se você quer saber o motivo, você deve saber o que pode * fazer no bash e como os comandos do bash parse:

primeiro, o que pode * fazer no bash:

  1. como um curinga no nome do arquivo glob

  2. multiplique

  3. 0 ou mais vezes no regex

    ...

e como os comandos do bash parse (simplificados, na verdade são muito complicados):

  1. substituição de parâmetros

  2. substituição de comandos

  3. globbing

    ...

Suponha que você hava a.txt b.txt no diretório atual, em expr 2 * 4 , após a substituição do parâmetro - > substituição de comando - > globbing, vai se tornar

expr 2 a.txt b.txt 4

qual causa não retornará a resposta correta.

No entanto, em expr 2 \* 4 , * é um personagem! Nenhuma substituição de parâmetro, substituição de comando, globbing afetará isso. então, expr obtenha 3 parâmetros 2 * 4 e ele retornará 8.

Em let var1=2*4 , bash faz uma substituição aritmética antes de globing, o comando após o pasing é let var1=8 . Se você tem 2a4 2b4 no diretório atual e você não usa let, apenas

var1=2*4
echo $var1

Ele retornará 2a4 2b4, NÃO 8.

Em var2=$((2*4)) , bash também faz uma substituição aritmética porque (()) é um operador aritmético.

PS: Se você quiser * ser um operador aritmético, mantenha-o em (()) $ [] ou usando let, por exemplo:

((var1 = 2 * 4)) or var1=$((2 * 4))
var1=$[2 * 4]

WHITESPESPES são permitidos!

    
por 26.12.2017 / 02:40

Tags