O que é a divisão de palavras? Por que é importante na programação de shell?

10

Estou ficando confuso sobre a função que a divisão de palavras desempenha em zsh . Eu não fui exposto a este conceito quando estou programando em C, Python ou MATLAB, e isso despertou meu interesse de por que a divisão de palavras parece ser algo específico para a programação shell.

Eu já li sobre a divisão de palavras neste e em outros sites antes, mas não encontrei uma explicação clara do conceito. A Wikipedia tem uma definição de divisão de palavras , mas não parece ter referências sobre como se aplica a shells Unix.

Veja um exemplo da minha confusão em zsh :

No Perguntas frequentes sobre o Z Shell , eu li o seguinte:

3.1: Why does $var where var="foo bar" not do what I expect?

In most Bourne-shell derivatives, multiple-word variables such as var="foo bar" are split into words when passed to a command or used in a for foo in $var loop. By default, zsh does not have that behaviour: the variable remains intact. (This is not a bug! See below.) The option SH_WORD_SPLIT exists to provide compatibility.

No entanto, no Z Shell Manual , leia o seguinte:

SH_WORD_SPLIT (-y) <K> <S>

Causes field splitting to be performed on unquoted parameter expansions. Note that this option has nothing to do with word splitting. (See Parameter Expansion.)

Por que isso diz que SH_WORD_SPLIT tem nada para fazer com a divisão de palavras? A palavra não está dividindo precisamente o que é isso tudo?

    
por Amelio Vazquez-Reina 12.12.2011 / 23:42

3 respostas

17

Os shells iniciais tinham apenas um único tipo de dados: strings. Mas é comum manipular listas de strings, geralmente ao passar vários nomes de arquivos como argumentos para um programa. Outro caso de uso comum para divisão é quando um comando gera uma lista de resultados: a saída do comando é uma cadeia, mas os dados desejados são uma lista de cadeias de caracteres. Para armazenar uma lista de nomes de arquivos em uma variável, você colocaria espaços entre eles. Então um script de shell como este

files="foo bar qux"
myprogram $files

chamado myprogram com três argumentos, pois o shell divide a string $files em palavras. Na época, os espaços nos nomes de arquivos eram proibidos ou amplamente considerados como Não Concluídos.

O shell Korn introduziu matrizes: você pode armazenar uma lista de strings em uma variável. O shell Korn permaneceu compatível com o shell Bourne então estabelecido, portanto expansões de variáveis nuas continuavam passando pela divisão de palavras e o uso de matrizes exigia alguma sobrecarga sintática. Você escreveria o trecho acima

files=(foo bar qux)
myprogram "${files[@]}"

O Zsh tinha matrizes desde o início e seu autor optou por um design de linguagem mais saudável em detrimento da compatibilidade com versões anteriores. Em zsh (sob as regras de expansão padrão) $var não executa a divisão de palavras; Se você quiser armazenar uma lista de palavras em uma variável, você deve usar uma matriz; e se você realmente quiser dividir palavras, pode escrever $=var .

files=(foo bar qux)
myprogram $files

Hoje em dia, espaços em nomes de arquivos são algo que você precisa lidar, porque muitos usuários esperam que eles funcionem e porque muitos scripts são executados em contextos sensíveis à segurança, onde um invasor pode estar no controle de nomes de arquivos. Portanto, a divisão automática de palavras geralmente é um incômodo; Portanto, meu conselho geral é sempre usar aspas duplas, por exemplo, escreva "$foo" , a menos que você entenda por que precisa da divisão de palavras em um caso de uso específico. (Observe que expansões de variáveis nuas sofrem também globbing).

    
por 13.12.2011 / 01:56
3

A divisão de palavras não é específica de shell.

A maioria dos programas que precisam analisar a entrada de texto usa alguma forma de divisão de palavras como primeiro passo. Isso é feito antes de identificar essas "palavras", números, operadores, strings, tokens e quaisquer entidades semelhantes que eles precisam processar.

O que é específico para os shells é que eles precisam construir adequadamente a lista de argumentos dos comandos chamados (C argc / argv, python sys.argv), incluindo a passagem de argumentos com espaços embutidos, argumentos vazios, delimitadores personalizados e assim por diante. Muitos shells usam a variável IFS para permitir alguma flexibilidade.

    
por 13.12.2011 / 00:33
3

Neste caso específico de Zsh, a divisão de palavras é definida de forma ligeiramente diferente da divisão de campos.

Considere prog a b c , ele será aprovado em três argumentos, independentemente de como você definir IFS . Esta é a divisão word .

Se você usar A="a b c"; prog $A , ele passará em três argumentos se IFS incluir espaço ou um argumento. Isto é campo dividido.

As definições aqui são sutis. O que o documento Zsh está tentando dizer é que, mesmo se você desativar essa opção, prog a b c ainda receberá argumentos separados (que é o que as pessoas sempre esperam).

    
por 11.03.2018 / 10:10

Tags