Expansão de uma variável de shell e efeito de glob e split nele

15

Este post contém duas perguntas separadas, mas acho que agrupá-las dará mais contexto. Eu passei por esta pergunta sobre as cotações em torno de variáveis , mas eu não entendo bem o que expansão de variável significa em primeiro lugar. Então, minha primeira pergunta é:

  1. O que é expansão de variáveis em unix / linux speak?

Uma segunda parte da minha pergunta está relacionada aos seguintes termos:

  1. glob
  2. dividido

O que isso significa e como eles afetam a expansão das variáveis? A resposta à pergunta original menciona o seguinte:

Think of the absence of quotes (in list contexts) as the split+glob operator.

As if echo $test was echo glob(split("$test")).

Não encontrei nenhuma resposta que abordasse diretamente o conceito de globbing e divisão , mas use esses termos diretamente para responder a outras perguntas como esta Unidade recente .

    
por Geek 12.01.2014 / 09:54

2 respostas

12

Expansão variável (o termo padrão é expansão de parâmetro , e também é às vezes chamado de substituição de variável ) basicamente significa substituir a variável pelo seu valor . Mais precisamente, isso significa substituir a construção $VARIABLE (ou ${VARIABLE} ou ${VARIABLE#TEXT} ou outras construções) por algum outro texto construído a partir do valor da variável. Este outro texto é a expansão da variável.

O processo de expansão é o seguinte. (Eu apenas discuto o caso comum, algumas configurações de shell e extensões modificam o comportamento).

  1. Pegue o valor da variável, que é uma string. Se a variável não estiver definida, use a string vazia.
  2. Se a construção incluir uma transformação, aplique-a. Por exemplo, se a construção for ${VARIABLE#TEXT} e o valor da variável começar com TEXT , remova TEXT do início do valor.
  3. Se o contexto exigir uma única palavra (por exemplo, entre aspas duplas ou no lado direito de uma atribuição ou dentro de um documento aqui), pare aqui. Caso contrário, continue com as próximas etapas.
  4. Divida o valor em palavras separadas em cada sequência de espaço em branco. (A variável IFS pode ser alterada para dividir em caracteres diferentes de espaço em branco.) O resultado não é mais uma string, mas uma lista de strings. Esta lista pode estar vazia se o valor contiver apenas espaço em branco.
  5. Trate cada elemento da lista como um padrão curinga de nome de arquivo, ou seja, um glob Se o padrão corresponder a alguns arquivos, ele será substituído pela lista de nomes de arquivos correspondentes, caso contrário, ele será deixado em paz.

Por exemplo, suponha que a variável foo contenha a* b* c* e o diretório atual contenha os arquivos bar , baz e paz . Então, ${foo#??} é expandido da seguinte forma:

  1. O valor da variável é a string de 8 caracteres a* b* c* .
  2. #?? significa remover os dois primeiros caracteres, resultando na string de 6 caracteres  b* c* (com um espaço inicial).
  3. Se a expansão estiver em um contexto de lista (ou seja, sem aspas duplas ou outro contexto semelhante), continue.
  4. Divida a sequência em palavras delimitadas por espaços em branco, resultando em uma lista de duas sequências: b* e c* .
  5. A string b* , interpretada como um padrão, corresponde a dois arquivos: bar e baz . A string c* não corresponde a nenhum arquivo, portanto, é deixada em paz. O resultado é uma lista de três strings: bar , baz , c* .

Por exemplo, echo ${foo#??} imprime bar baz c* (o comando echo une seus argumentos com um espaço entre eles).

Para mais detalhes, consulte:

por 13.01.2014 / 03:55
11

glob / split

Vou pegar o glob / split primeiro. @ resposta de Stephane você vinculado está usando esses termos em um sentido geral. Eles não são comandos reais ou algo assim, apenas pseudo-operações.

O split("$test") dividiria o conteúdo de "$ test" em um "array" de elementos.

O glob(...) tomaria então o cuidado de expandir qualquer um desses elementos que contenham caracteres de globalização, como * ou intervalos [1-2] .

Exemplo

Diga que nossa string $test é a seguinte.

$ test="afile[1-2] afile[3-5]"

Também vamos dizer que temos um diretório com alguns arquivos.

$ ls -1
afile1
afile2
afile3
afile4
afile5

Agora, se tentarmos ecoá-lo sem aspas, você deve notar que nossa sequência foi dividida em espaços e, em seguida, todos os caracteres globbing foram expandidos.

$ echo $test
afile1 afile2 afile3 afile4 afile5

No entanto, se fôssemos citar a variável quando a passássemos como um argumento para echo , obteríamos a string literal original.

$ echo "$test"
afile[1-2] afile[3-5]

expansão variável

O termo expansão variável destina-se a cobrir a operação básica que o shell está executando como parte de suas operações básicas. O shell é responsável por analisar a entrada e depois executar essa entrada, uma vez que ela é considerada sintaticamente correta.

No nosso exemplo anterior. Quando a variável $test foi apresentada a echo não citada, estávamos dizendo ao shell para ir em frente e dividir esses argumentos e, em seguida, globá-los.

Quando foi citado, estávamos basicamente desabilitando esse recurso com qualquer variável que envolvesse com aspas duplas.

Exemplo

Aqui estão alguns exemplos adicionais de globbing e divisão.

glob / splitting acontece automaticamente

$ echo file{1..3}
file1 file2 file3

$ echo file{1..3} dir{a..b}
file1 file2 file3 dira dirb

$ echo dir{z..w} file{A..D}
dirz diry dirx dirw fileA fileB fileC fileD

$ echo dir{z..w} file{A..B} fileC
dirz diry dirx dirw fileA fileB fileC

glob / splitting desativado por meio de cotação dupla

$ echo "dir{z..w} file{A..B} fileC"
dir{z..w} file{A..B} fileC

$ echo "dir{z..w} file{A..B}"
dir{z..w} file{A..B}
    
por 12.01.2014 / 10:54