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

18

Este post contém duas perguntas separadas, mas acho que agrupá-las dará mais contexto. Eu passei por essa pergunta entre aspas em torno de variáveis, mas não entendo bem o que significa expansão de variável em primeiro lugar. Então, minha primeira pergunta é:

  1. O que é expansão variável no unix / linux speak?

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

  1. glob
  2. Dividido

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

Pense na ausência de aspas (em contextos de lista) como o operador split + glob.

Como se echo $ test fosse echo glob (split ("$ test")).

Não consegui encontrar respostas que abordassem diretamente o conceito de globbing e split, mas usem esses termos diretamente para responder a outras perguntas como esta recente .

Nerd
fonte

Respostas:

15

Expansão variável (o termo padrão é expansão de parâmetro e também é chamado de substituição de variável ) basicamente significa substituir a variável pelo seu valor. Mais precisamente, isso significa substituir a $VARIABLEconstrução (ou ${VARIABLE}ou ${VARIABLE#TEXT}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. (Apenas discuto o caso comum, algumas configurações e extensões do shell modificam o comportamento.)

  1. Pegue o valor da variável, que é uma string. Se a variável não estiver definida, use a sequência vazia.
  2. Se a construção incluir uma transformação, aplique-a. Por exemplo, se a construção é ${VARIABLE#TEXT}e o valor da variável começa com TEXT, remova TEXTdo 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 IFSpode ser alterada para dividir em caracteres que não sejam espaços em branco.) Portanto, o resultado não é mais uma sequência, mas uma lista de sequências. 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 globo . Se o padrão corresponder a alguns arquivos, ele será substituído pela lista de nomes de arquivos correspondentes, caso contrário, será deixado sozinho.

Por exemplo, suponha que a variável foocontém a* b* c*eo diretório atual contém os arquivos bar, baze paz. Em seguida, ${foo#??}é expandido da seguinte forma:

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

Por exemplo, echo ${foo#??}impressões bar baz c*(o comando echojunta seus argumentos com um espaço no meio).

Para mais detalhes, consulte:

Gilles 'SO- parar de ser mau'
fonte
2
Note-se que ele é chamado de expansão de parâmetros porque se aplica a variáveis ( $var) e outros tipos de parâmetros como $1, $#, $?, $-...
Stéphane Chazelas
12

glob / split

Vou pegar o glob / split primeiro. A resposta de @ Stephane à qual você se vinculou é usar esses termos em um sentido geral. Eles não são comandos reais ou algo parecido, apenas pseudo-operações.

O split("$test")iria dividir o conteúdo de "$ test"-se em um "array" de elementos.

Em glob(...)seguida, tomaríamos o cuidado de expandir qualquer um desses elementos que contenham caracteres globbing do shell, como *intervalos [1-2].

Exemplo

Digamos 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 nele.

$ ls -1
afile1
afile2
afile3
afile4
afile5

Agora, se tentarmos repeti-lo sem aspas, você deve notar que nossa string foi dividida em espaços e, em seguida, quaisquer caracteres brilhantes foram expandidos.

$ echo $test
afile1 afile2 afile3 afile4 afile5

No entanto, se citássemos a variável quando a passássemos como argumento 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, em seguida, executá-la assim que for considerada sintaticamente correta.

No nosso exemplo anterior. Quando a variável $testfoi apresentada entre echoaspas, estávamos dizendo ao shell para seguir em frente e dividir esses argumentos e depois enviá-los.

Quando foi citado, estávamos essencialmente desativando esse recurso com qualquer variável que envolvemos com aspas duplas.

Exemplo

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

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 aspas duplas

$ 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}
slm
fonte
Eu não sabia que os intervalos também funcionavam em ordem inversa.
Joe Joe