Como entender a ordem entre as expansões?

3

do POSIX 7:

The order of word expansion shall be as follows:

  1. Tilde expansion (see Section 2.6.1), parameter expansion (see Section 2.6.2), command substitution (see Section 2.6.3), and arithmetic expansion (see Section 2.6.4) shall be performed, beginning to end. See item 5 in Section 2.3.

  2. Field splitting (see Section 2.6.5) shall be performed on the portions of the fields generated by step 1, unless IFS is null.

  3. Pathname expansion (see Section 2.6.6) shall be performed, unless set −f is in effect.

  4. Quote removal (see Section 2.6.7) shall always be performed last.

  1. Faça expansão de til, expansão de parâmetro, substituição de comando, e expansão aritmética executar na ordem especificada?

    A ordem entre eles é importante? Se sim, como entenderemos por que o pedido é como especificado?

  2. Por que a expansão do nome do caminho acontece após a divisão do campo, enquanto outras expansões antes da divisão do campo?

    Em particular, tanto a expansão do til quanto a expansão do nome do caminho são sobre nomes de arquivos e nomes de arquivos, por que eles são colocados de maneira diferente em relação à divisão de campo?

  3. Não há expansão de chave no POSIX?

  4. Eu noto "expansão de palavras". As expansões aplicam-se apenas a tokens com o identificador de token WORD e não a tokens com outros identificadores de token (por exemplo, NAME, operador específico, NEWLINE, IO_NUMBER, ASSIGNMENT)?

por Tim 16.03.2016 / 19:53

3 respostas

2

Expansão de til, expansão de parâmetro, substituição de comando e expansão aritmética são listadas na mesma etapa. Isso significa que eles são executados ao mesmo tempo . O resultado da expansão de til não sofre expansão de parâmetro, o resultado da expansão de parâmetro não sofre expansão de til e assim por diante. Por exemplo, se o valor de foo for $(bar) qux , a palavra $foo será expandida para $(bar) qux na etapa 1; o texto resultante da expansão do parâmetro não está sujeito a nenhuma transformação adicional na etapa 1, mas é dividido na etapa 2.

"Começando até o final" significa processamento da esquerda para a direita, o que importa, por exemplo, quando atribuições ocorrem: a=1; echo $a$((a=2))$a imprime 122 , porque é executada a expansão aritmética de $((a=2)) , definindo a para 2, entre a expansão de parâmetro do primeiro $a e a expansão de parâmetro do segundo $a .

O motivo do pedido é o uso histórico. POSIX geralmente segue a implementação existente, raramente especifica novo comportamento. Existem várias conchas ao redor; na maior parte, POSIX segue o shell Korn , mas omite a maioria dos recursos que não estão presentes no Bourne shell (como o shell Bourne é largamente abandonado, a próxima versão do POSIX provavelmente incluirá novos recursos do ksh).

A razão pela qual o shell Bourne executou a expansão de parâmetro e a divisão de campo e globbing é que ele permitiu que um glob fosse armazenado em uma variável: você pode definir a to *.txt *.pdf e usar $a para representar o lista de nomes de arquivos correspondentes a *.txt seguido pela lista de nomes correspondentes a *.pdf (assumindo que ambos os padrões correspondam). (Não estou dizendo que esse é o melhor design possível, apenas que ele foi projetado dessa maneira.) É menos claro para mim por que alguém desejaria que a substituição de comando fosse colocada em uma etapa específica na shell Bourne; no shell Korn, sua sintaxe $(…) está próxima da expansão do parâmetro ${…} , portanto, faz sentido realizá-las em conjunto.

A colocação da expansão do til é uma esquisitice histórica. Teria mais sentido colocá-lo posteriormente, para que você pudesse escrever ~$some_user e expandi-lo para o diretório inicial do usuário cujo nome é o valor da variável some_user . Eu não sei porque não foi feito dessa maneira. Esse pedido exige até mesmo uma declaração especial de que o resultado da expansão do til não passa por outras expansões (passando pela passagem citada, se HOME for /foo bar , então ~ expandiria para as duas palavras /foo e bar devido à divisão do campo, mas nenhum shell faz isso e o POSIX.2008 declara explicitamente que “o nome do caminho resultante da expansão do til deve ser tratado como se fosse citado”).

Não há expansão de chave no POSIX, caso contrário, a especificação a declararia.

A expans� do Word �realizada apenas em WORDs e com ressalvas mencionadas nas sec�es seguintes (por exemplo, a separa�o de campos e gera�o de caminhos apenas s� executadas em contextos que permitem m�tiplas palavras, e. g., entre aspas duplas). NAMEs, NEWLINEs, IO_NUMBERs e assim por diante não contêm nada que possa ser expandido de qualquer maneira.

    
por 17.03.2016 / 01:10
2

Em relação a (1), a ordem é baseada na implementação existente. Se as pessoas envolvidas na escrita soubessem de ordenação diferente para diferentes reservatórios que fossem considerados padrão , eles forneceriam alguma margem de manobra no texto para permitir isso. Conforme expresso em 2.6 Expansões do Word , não há sugestões que outra encomenda poderia cumprir com a norma.

Mais uma vez, com (2), tenha em mente que isso é baseado na implementação existente. As razões para a implementação original não são necessariamente encontradas no padrão, embora para algumas áreas de desacordo interessantes (por exemplo, BSD versus SVr4), uma seção rationale é fornecida para resumir a razão pela qual o comitê escolheu escolha uma das alternativas conflitantes.

Para (3), o que você mencionou como "expansão de contraventores" pode ser o mesmo que .2 Expansão de Parâmetros (embora existam outras possibilidades, não necessariamente em POSIX).

Finalmente (4), lembre-se de que um NAME é um determinado tipo de WORD . A expansão do Word se aplicaria a nomes .

    
por 16.03.2016 / 21:30
2
  1. Primeira ordem de quatro expansões:

O acionador para cada expansão é distinto: Expansão de til ~ , expansão de parâmetro $name e ${name} , substituição de comando $() e ' ' e expansão aritmética $((...))) . Portanto, a ordem não importa muito, pois não há como confundir uma com a outra, e cada expansão é realizada apenas uma vez. Um token que tenha sido sujeito a expansão de parâmetro não estará sujeito à substituição de comando (por exemplo). Uma expansão que pode confundir as coisas é a expansão aritmética porque (dentro dela) pode haver expansão de parâmetro, expansão, expansão de string, substituição de comando e remoção de cotação. E expansões aritméticas podem ser aninhadas. Mas tudo isso acontece dentro de uma expansão aritmética já detectada, e não fora dela.

A ordem que mais importa é da esquerda para a direita.

Depois de tudo isso, os resultados das expansões acima (se não forem citadas) estarão sujeitos à divisão de campos e à expansão do nome de caminho (nessa ordem).

Todas as expansões estarão sujeitas à remoção de cotações.

  1. Não, não há expansão de chave no POSIX.
  2. Word e token costumam ser usados para indicar a mesma ideia nesse caso.
por 16.03.2016 / 22:49

Tags