Expansão aritmética da shell com cotações

4

No Bash e no Dash, usar aspas em uma Expansão Aritmética é ilegal:

$ bash -c 'x=123;echo $(("$x"))'
bash: "123": syntax error: operand expected (error token is ""123"")
$ dash -c 'x=123;echo $(("$x"))'
dash: 1: arithmetic expression: expecting primary: ""123""

Bash dá o mesmo erro quando invocado como sh. O Ksh e o Bourne Shell do FreeBSD não se importam, no entanto:

$ ksh -c 'x=123;echo $(("$x"))'
123
$ sh -c 'x=123;echo $(("$x"))'
123

De acordo com o Manual de referência do Bash :

The expression is treated as if it were within double quotes, but a double quote inside the parentheses is not treated specially. All tokens … undergo … quote removal.

(que é essencialmente o mesmo que POSIX diz.)

Finalmente, há uma distinção aqui em como o Bash manipula $(( )) comparado a outros contextos aritméticos como (( )) (como em expressões condicionais, por exemplo). Este último está bem com aspas.

Ou eu não entendo o que quote removal significa aqui, ou isso é um bug em algumas dessas implementações do shell. Se é o primeiro, o que significa "remoção de cotação"? Ou é apenas um bug?

    
por kojiro 13.01.2016 / 23:20

1 resposta

0

Estou dividido entre saber se isso é uma implementação deficiente ou uma documentação deficiente. Bash diz isso sobre remoção de cotações:

Quote Removal

After the preceding expansions, all unquoted occurrences of the characters \, ', and " that did not result from one of the above expansions are removed.

Acho que a chave pode ser "todas as ocorrências não citadas " nesse parágrafo. Tudo dentro de $(( )) é tratado como se estivesse entre aspas duplas, de acordo com a documentação. Esses personagens são todos citados se estiverem dentro dos parênteses, fazendo com que a remoção das citações seja essencialmente um noop. Por exemplo, observe como os outros caracteres "removidos" são tratados (observe também como o espaço à direita é preservado, devido à maneira como as cadeias de caracteres citadas são analisadas):

$ echo $(( '5' ))
bash: '5' : syntax error: operand expected (error token is "'5' ")
$ echo $(( \ ))
bash: \ : syntax error: operand expected (error token is "\ ")

Percorrendo o código-fonte, as cotações precisam ser balanceadas, como resultado do código que procura para identificar se $(( )) é matemática ou uma subexpressão legada aninhada. Quando a string é identificada como uma expressão aritmética, ela é então analisada como se fosse duplicada - o que significa todos os caracteres que são considerados antes da remoção da cotação.

Pessoalmente, isso é parte do porque eu prefiro o ksh - especialmente para matemática. Ele trata o single-citado 5 acima como uma string C que é avaliada como 53, por exemplo. man ascii para ver porque isso faz sentido. :)

    
por 16.08.2016 / 00:41