Eu posso ter algo absolutamente errado, mas me parece convincente, que definir o IFS como um dos comandos na lista de tarefas / tarefas não tem absolutamente nenhum efeito.
O IFS externo (fora da while
construção) prevalece em todos os exemplos mostrados no script abaixo.
O que está acontecendo aqui? Eu entendi errado o que o IFS faz nessa situação? Eu esperava que os resultados da divisão de matriz fossem mostrados na coluna "esperado".
#!/bin/bash
xifs() { echo -n "$(echo -n "$IFS" | xxd -p)"; } # allow for null $IFS
show() { x=($1)
echo -ne " (${#x[@]})\t |"
for ((j=0;j<${#x[@]};j++)); do
echo -n "${x[j]}|"
done
echo -ne "\t"
xifs "$IFS"; echo
}
data="a b c"
echo -e "----- -- -- \t --------\tactual"
echo -e "outside \t IFS \tinside"
echo -e "loop \t Field \tloop"
echo -e "IFS NR NF \t Split \tIFS (actual)"
echo -e "----- -- -- \t --------\t-----"
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while read; do echo -ne '\t 1'; show "$REPLY"; done
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne '\t 2'; show "$REPLY"; done
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne '\t 3'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while read; do echo -ne '\t 4'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne '\t 5'; show "$REPLY"; done
IFS=" "; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne '\t 6'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while read; do echo -ne '\t 7'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while IFS=" " read; do echo -ne '\t 8'; show "$REPLY"; done
IFS=; xifs "$IFS"; echo "$data" | while IFS=b read; do echo -ne '\t 9'; show "$REPLY"; done
IFS=b; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne '\t10'; show "$REPLY"; done
IFS=b; xifs "$IFS"; echo "$data" | while IFS=" " read; do echo -ne '\t11'; show "$REPLY"; done
echo -e "----- -- -- \t --------\t-----"
Resultado:
----- -- -- -------- actual
outside IFS inside assigned
loop Field loop # inner
IFS NR NF Split IFS # expected IFS
----- -- -- -------- ----- # --------- --------
20090a 1 (3) |a|b|c| 20090a #
20090a 2 (3) |a|b|c| 20090a # |a b c| IFS=
20090a 3 (3) |a|b|c| 20090a # |a | c| IFS=b
20 4 (3) |a|b|c| 20 #
20 5 (3) |a|b|c| 20 # |a b c IFS=
20 6 (3) |a|b|c| 20 # |a | c| IFS=b
7 (1) |a b c| #
8 (1) |a b c| # |a|b|c| IFS=" "
9 (1) |a b c| # |a | c| IFS=b
62 10 (2) |a | c| 62 # |a b c| IFS=
62 11 (2) |a | c| 62 # |a|b|c| IFS=" "
----- -- -- -------- ----- --------- -------
$IFS
são removidos no início / fim da linha de entrada, presumo? (Que é como ele funciona.)a<tab>b
emread var
resultará em var com o valora<space>b
, mas se você tiverIFS='<newline>' read var
, o valor de var seráa<tab>b
.Simplificando, você deve ler mais de uma variável por vez para que a
IFS=<something> read ...
construção tenha um efeito visível em seus exemplos 1 .Você perde o escopo dos
read
exemplos. Não há modificação do IFS dentro do loop nos seus casos de teste. Permita-me apontar exatamente onde o segundo IFS tem efeito em cada uma de suas linhas:É como qualquer programa executado no shell. A variável que você (re) define na linha de comando afeta a execução do programa. E apenas isso (já que você não exporta). Portanto, para usar o redefinido
IFS
nessa linha, você precisará pedirread
para atribuir valores a mais de uma variável . Veja estes exemplos:1 Como acabei de aprender com Gilles , pode haver um benefício em definir
IFS=''
(em branco) ao ler apenas um campo: evita truncamento de espaço em branco no início da linha.fonte
IFS= read
usado preferencialmente apenas para redefinir a variável de ambiente IFS". Eu não sabia, então, que variáveis locais poderiam ser definidas pelo chamador de um comando. Essa foi a resposta para essa pergunta. Ele evoluiu ainda mais para abordar o ponto principal dessa pergunta, mas quando percebi isso, eu já tinha feito essa pergunta ... Talvez as duas perguntas sejam tão parecidas quanto duassed
, então meu sentimento é mantê-lo como está ... Mais títulos para os googlers no Google.