Estou tentando verificar o seguinte que li aqui :
É importante lembrar que o shell executa todos os tipos de expansão que descrevemos em ordem. Isso significa que a expansão de palavras é executada antes da expansão do nome do caminho. Portanto, se você percorrer os resultados de um caminho expandido, a divisão de palavras não será realizada nesses resultados.
Eu escrevi um script muito simples que estou usando para verificar a citação acima sobre a ordem das operações de expansão de palavras e nomes de caminhos:
$ cat test.sh
for path in /home/john/Downloads/*.xlsx
do
echo "${path}"
done
O resultado
$ ./test.sh
/home/john/Downloads/CCIE-Collaboration-v3-Learning-Matrix.xlsx
/home/john/Downloads/x y.xlsx
Pelo que li, a expansão de palavras acontece antes da expansão de caminhos, e eles usaram um script muito semelhante a este para demonstrar isso. Mas na verdade não entendo como este exemplo demonstra isso. Pelo que posso ver, "caminho" é uma variável, e depois que a variável identificar um caminho, esse será $caminho. Então, onde uma palavra terra poderia entrar nisso, já que não consigo ver nenhuma palavra que possa ser considerada para expansão.
Para esclarecer, se executarmos a primeira iteração, $path ficará vazio até verificar "/home/john/Downloads/*.xlsx", momento em que será definido como "/home/john/Downloads/CCIE-Collaboration -v3-Learning-Matrix.xlsx", pois esta é a primeira entrada. Nesse ponto $path foi definido. Não houve oportunidade de aplicar a expansão de palavras (por exemplo, eles estão dizendo que a expansão de palavras é aplicada a "nulo" antes que o nome do caminho real defina o primeiro resultado)?
Acredito que o que eles estão tentando explicar é que depois que o shell se expandiu
/home/john/Downloads/*.xlsx
para/home/john/Downloads/CCIE-Collaboration-v3-Learning-Matrix.xlsx
and/home/john/Downloads/x y.xlsx
("expansão do nome do caminho"), ele não tentou dividi-lo novamente em/home/john/Downloads/CCIE-Collaboration-v3-Learning-Matrix.xlsx
,/home/john/Downloads/x
andy.xlsx
("divisão de palavras" - não "expansão de palavras"). Tudo isso antes dofor
loop começar a atribuir valores à variável. Portanto, o loop apenas itera sobre dois valores em vez dos três que teríamos visto se a divisão de palavras fosse executada no resultado da expansão do nome do caminho. Nada disso tem a ver com o que está acontecendo dentro do corpo do loop.Por outro lado, se você tivesse
for i in $(echo a b c)
, o shell faria a divisão de palavras no resultado da substituição do comando, e você veria três iterações de loop em vez daquela que você obteriafor i in "$(echo a b c)"
.Quando os autores escreveram word expansion , um termo que eles não usam em nenhum outro lugar da página (mas um que fui informado está perfeitamente correto, veja as especificações POSIX aqui ), eles pareciam estar se referindo à operação de divisão, o que eles chamam de "divisão de palavras". Este é o processo pelo qual o shell dividirá as coisas no valor da
$IFS
variável (normalmente definida como espaço, tabulação e nova linha). Por exemplo, considere este script (retirado daqui , que é uma ótima referência e recomendo fortemente que você o leia):O script simplesmente imprimirá seus argumentos, mostrando como eles são divididos em palavras. Tente executar com entradas diferentes:
Aqui, a string foi dividida
apple orange "passion fruit"
em três "palavras"apple
eorange
.passion fruit
Isso é divisão de palavras. Observe como as cotações são protegidaspassion fruit
contra divisão.Agora, como afirma o artigo, a ordem é importante. Se você ler a seção "Expansão" do manual do bash , encontrará:
A parte relevante aqui é que a divisão de palavras, o que mostrei acima, acontece antes da expansão do nome do arquivo (caminho). Seu equívoco está aqui:
Não,
$path
já está definido nesse ponto, não é expandido para/home/john/Downloads/CCIE-Collaboration-v3-Learning-Matrix.xlsx
dentro do loop, mas antes do início do loop. Podemos dividir os dois, divisão de palavras e expansão de nome de caminho, usando um script ligeiramente diferente do que você tem:Experimente esse script em um diretório com o seguinte conteúdo:
A saída é:
Então, o que está acontecendo?
A variável
$words
é dividida em palavras no valor de$IFS
. Isso resulta em 3 palavras :z
ey.xlsx
.*.xlsx
A seguir, cada uma das três palavras sofre expansão de caminho. Isso deixa
x
ey.xlsx
inalterado, pois eles não podem ser expandidos para um caminho, mas*.xlsx
se tornamx y.xlsx
eCCIE-Collaboration-v3-Learning-Matrix.xlsx
.O que os autores estão tentando enfatizar é que, como a divisão de palavras já ocorreu no momento em que o shell se expande
*.xlsx
parax y.xlsx
eCCIE-Collaboration-v3-Learning-Matrix.xlsx
, nenhuma divisão adicional de palavras ocorre ex y.xlsx
é tratada como uma única palavra, apesar de conter um espaço.Observe que a primeira versão desta resposta estava errada porque eu estava confundindo tokenização com divisão de palavras.
A frase "Isso significa que a expansão de palavras é executada antes da expansão do nome do caminho." na citação não há sentido, uma vez que a fonte nunca define o que deveria ser "expansão de palavras". Na próxima frase, eles mencionam a divisão de palavras, que é descrita anteriormente na página e é provavelmente o que eles queriam dizer. Portanto, ignore a frase "expansão de palavras", ela está errada nesse contexto, pura e simplesmente .
A próxima frase da citação faz mais sentido:
Considere o seguinte, criamos os dois arquivos
oneword
emtwo words
um diretório vazio e fazemos um loop./*
:A saída é a seguinte, mostrando que o loop iterou sobre os dois itens
./oneword
,./two words
sendo esses os resultados diretos da expansão do nome do caminho, e o último nome do arquivo não foi dividido posteriormente.Se a divisão do Word ocorresse após a expansão do nome do caminho, o segundo nome do arquivo seria dividido ainda mais em
./two
words
e o loop seria executado um total de três vezes. (Assumindo o padrãoIFS
.)O Q acima continua com
Mas, como mencionado acima, isso não tem sentido. A fonte a que você se refere não define o que "expansão de palavras" significa para eles e não está claro o que você quer dizer com a frase. Não é sua culpa: você está sendo confundido por uma fonte que não consegue manter sua terminologia correta.
Agora, tecnicamente, a especificação POSIX usa a frase "expansão de palavras" para todas as expansões de til, expansão de parâmetros, substituição de comandos, expansão aritmética, divisão de campos (geralmente chamada de divisão de palavras), expansão de nome de caminho/nome de arquivo e remoção de aspas. Mas o contexto em que sua fonte está usando a frase não faz sentido com essa definição. A expansão de palavras não pode acontecer "antes" da expansão de caminho, pois a expansão de palavras inclui a expansão de caminho.
Novamente, depende do que você quer dizer. O sentido POSIX de "divisão de palavras" inclui praticamente tudo, portanto, no script no Q, há a "expansão de palavras" (expansão de nome de caminho) nos
/home/john/Downloads/*.xlsx
nomes dos arquivos e a "expansão de palavras" (expansão de parâmetros)"${path}"
no atual valor da variávelpath
. (E meu script acima também apresenta um caso de expansão aritmética.)