Comportamento de expansão de campo inesperado por bash para loop

1

Estou tendo problemas para conciliar todas as regras de expansão de campos no linux / unix, então estou experimentando. Aqui está um exemplo que, baseado em minha leitura, não é consistente com o que eu esperaria.

~$ IFS=$', \t\n'
~$ for i in 1 2 3; do echo num:"$i"; done
num:1
num:2
num:3
~$ myvar=1,2,3
~$ for i in $myvar; do echo num:"$i"; done
num:1
num:2
num:3
~$ for i in 1,2,3; do echo num:"$i"; done
num:1,2,3

A última saída para mim é completamente inesperada. Onde posso encontrar a regra em que a expansão de campo só acontece em um bash para loop para variáveis?

Parece-me que o bash for loop não está honrando o valor IFS que eu configurei no começo. Eu estou entendendo mal alguma coisa?

    
por Frank Bryce 10.02.2016 / 17:44

2 respostas

1

Execute este comando:

LESS=+/'^ *IFS *The' man bash

Para ler ("ênfase minha"):

IFS
The Internal Field Separator that is used for word splitting after expansion and to split lines into words with the read builtin command. The default value is '<space><tab><newline>'.

Isso significa que, se a expansão não tiver ocorrido, a divisão de campo do IFS também não ocorrerá.

Bem, na verdade, o spliting ocorre na linha original, mas com o conjunto de fixações de metacaracteres | & ; ( ) < > espaço separador

A vírgula , não é um metacaractere e não é usada para dividir.

O capítulo sete deste livro tem mais detalhes sobre o processamento de linha de comando:

  1. Splits the command into tokens that are separated by the fixed set of metacharacters: SPACE, TAB, NEWLINE, ;, (, ), <, >, |, and &. Types of tokens include words, keywords, I/O redirectors, and semicolons.
  1. Takes the parts of the line that resulted from parameter, command, and arithmetic substitution and splits them into words again. This time it uses the characters in $IFS as delimiters instead of the set of metacharacters in Step 1.
    
por 11.02.2016 / 04:25
2

Desdobramento de campos só se aplica ao resultado da expansão de parâmetros, substituição de comandos e expansão aritmética que não ocorreu entre aspas duplas, não a string literal.

Usando $myvar , você tem o efeito como glob(split(1,2,3)) , split(1,2,3) com , contém em IFS return 1 , 2 e 3 , glob(1 2 3) return 1 , 2 e 3 .

A string literal 1,2,3 não foi afetada por esse processo e apenas retorna como está.

    
por 10.02.2016 / 17:55

Tags