Como entender esta descrição POSIX sobre '(', ')' e 'teste'?

1

De POSIX 2013 :

The XSI extensions specifying the -a and -o binary primaries and the '(' and ')' operators have been marked obsolescent. (Many expressions using them are ambiguously defined by the grammar depending on the specific expressions being evaluated.) Scripts using these expressions should be converted to the forms given below. Even though many implementations will continue to support these obsolescent forms, scripts should be extremely careful when dealing with user-supplied input that could be confused with these and other primaries and operators. Unless the application developer knows all the cases that produce input to the script, invocations like:

test "$1" -a "$2"

should be written as:

test "$1" && test "$2"

  1. "os operadores '(' e ') foram marcados como obsoletos".

    São ( e ) os operadores que agrupam comandos e criam subshell?

    Se eles estiverem obsoletos, quais são seus substitutos?

  2. O test "$1" -a "$2" deve ser substituído por test "$1" && test "$2" ou por (( test "$1" && test "$2" )) ?

    Não precisamos do ((...)) para retornar 0 ou 1 como test no comando original?

por Tim 19.03.2016 / 09:38

2 respostas

6

Are ( and ) the operators that group commands, and create subshell?

Não, o documento refere-se aos operadores para agrupar expressões usando test :

test 0 -eq 0 -a \( 0 -eq 1 -o 1 -eq 1 \)

If they are obsolete, what are their replacement?

Os substitutos são () e {} , que, similarmente, agrupam comandos no nível do shell:

test 0 -eq 0 && (test -0 -eq 1 || test 1 -eq 1)
test 0 -eq 0 && { test -0 -eq 1 || test 1 -eq 1; }

É muito fácil ver o padrão: todo operador usado em test para expressões é substituído pelo equivalente do shell para comandos.

Should test "$1" -a "$2" be replaced by test "$1" && test "$2", or by (( test "$1" && test "$2" ))?

Deve ser substituído por test "$1" && test "$2" ; (()) é usado para expansão aritmética e não tem relação com o status de saída dos comandos, já que seu objetivo é avaliar expressões aritméticas. Por exemplo, isso seria válido:

(( $(test 1 -eq 1 && echo $?) && $(test 0 -eq 0 && echo $?) ))

(observe as substituições de comando, que são substituídas pelos status de saída dos comandos internos, 0 e 0 ; a expressão avaliada é, na verdade, (( 0 && 0 )) ).

Mas isso causa um erro de sintaxe:

(( test 1 -eq 1 && test 0 -eq 0 ))
$ (( test 1 -eq 1 && test 0 -eq 0 ))
bash: ((: test 1 -eq 1 && test 0 -eq 0 : syntax error in expression (error token is "1 -eq 1 && test 0 -eq 0 ")
    
por 19.03.2016 / 10:15
1

Para enfatizar um fato muito importante em uma linguagem mais simples:

Os caracteres que você digita na tela podem ou não ser "vistos" (recebidos) pelo comando que você está invocando. Você provavelmente está familiarizado com isso; isso acontece toda vez que você cita algo.

O shell vê todos os caracteres que você digita. O shell tem suas próprias regras para o que faz com esses caracteres. Por exemplo, o comando echo "vê" exatamente a mesma coisa em cada uma das instâncias a seguir:

$ echo hello
hello
$ echo "hello"
hello
$ echo 'hello'
hello
$ echo \h\e\l\l\o
hello
$ echo 'h'"e"\l$'lo'
hello
$ somevar=hello;echo $somevar
hello
$ somevar='h'"el"\l\o;echo $somevar
hello
$ 

Da mesma forma que as aspas e barras invertidas acima nunca são "vistas" pelo comando echo , o shell manipula parênteses especialmente. Então, quando não são citados, eles não são vistos por nada além do shell.

Um bom exemplo disso é o comando find , que aceita parênteses como argumentos . Para que os parênteses atinjam o comando find e não sejam interpretados especialmente pelo shell, eles devem ser citados ou escapados para remover seu significado especial para o shell. Note que as aspas e as fugas não não alcançam o comando find ; somente os parênteses fazem:

(De outra pergunta neste site:)

# What you type:
find ~ \( -type f '-ex'ec ch\mod 600 {} + ')' -o \
       "(" -type d -exec c"hmo"d 700 {} ';' \)
# What the find command sees:
/home/tim ( -type f -exec chmod 600 {} + ) -o ( -type d -exec chmod 700 {} ; )
# If you typed this...
find ~ \( -type f -exec chmod 600 {} + ) -o \
       \( -type d -exec chmod 700 {} + \)
# ...find doesn't see anything, because bash runs into an error condition
# before it can even parse the line.  That close paren is special to bash.

Existe também uma gíria relacionada a isso. Quando você pretende ter um comando "ver" um caractere especial (geralmente uma aspa ou aspas duplas, mas também pode incluir barras invertidas ou caracteres de espaço) e devido a um erro em suas citações e escape, o comando nunca vê esse caractere, nós digamos que a concha "comeu" a citação.

Um exemplo divertido de citar (e as dificuldades que podem cercá-lo) incluem: Escreva um comando ssh que faça login em um servidor remoto, inicie uma sessão bash e execute um comando sed para modificar um SQL consulta que é armazenada em um arquivo para que seja citado corretamente para inclusão em uma mensagem HTTP.

Com tudo isso dito, aqui está a resposta curta para:

  1. "the '(' and ')' operators have been marked obsolescent".

Are ( and ) the operators that group commands, and create subshell?

If they are obsolete, what are their replacement?

Os parênteses ainda têm um significado especial para o shell, e isso não é obsoleto. O que é obsoleto é passar parênteses ao comando test (citando-os para evitar que o shell os coma).

* Isso depende claramente da sua definição de "diversão".

    
por 19.03.2016 / 17:24