Como faço para impedir que `read` com` IFS` junte caracteres de espaço em branco? [duplicado]
Pegue este pedaço de código que lê dados separados por |
DATA1="Andreas|Sweden|27"
DATA2="JohnDoe||30" # <---- UNKNOWN COUNTRY
while IFS="|" read -r NAME COUNTRY AGE; do
echo "NAME: $NAME"; echo "COUNTRY: $COUNTRY";
echo "AGE: $AGE"; done<<<"$DATA2"
RESULTADO:
NOME: JohnDoe
PAÍS:
IDADE: 30
Deve funcionar de forma idêntica a este pedaço de código, onde estamos fazendo exatamente a mesma coisa, apenas usando \t
como separador em vez de|
DATA1="Andreas Sweden 27"
DATA2="JohnDoe 30" # <---- THERE ARE TWO TABS HERE
while IFS=$'\t' read -r NAME COUNTRY AGE; do echo "NAME: $NAME";
echo "COUNTRY: $COUNTRY"; echo "AGE: $AGE";
done<<<"$DATA2"
Mas isso não acontece.
RESULTADO:
NOME: JohnDoe
PAÍS: 30
IDADE:
Bash, ou read
ou IFS
ou alguma outra parte do código está aglutinando os espaços em branco quando não deveria. Por que isso está acontecendo e como posso corrigir isso?
Respostas
bash
está se comportando exatamente como deveria. Da bash
documentação:
O shell trata cada caractere do IFS como um delimitador e divide os resultados das outras expansões em palavras nesses caracteres. Se IFS é definida, ou o seu valor é exatamente
<space><tab><newline>
, o padrão, então seqüências de<space>
,<tab>
e<newline>
no início e no final dos resultados das expansões anteriores são ignorados, e qualquer sequência de caracteres IFS que não esteja no início ou no final serve para delimitar palavras. Se IFS tiver um valor diferente do padrão, as sequências de espaço de caracteres de espaço em branco e tabulação serão ignoradas no início e no final da palavra, desde que o caractere de espaço em branco esteja no valor de IFS (um caractere de espaço em branco IFS). Qualquer caractere em IFS que não seja um espaço em branco IFS, junto com quaisquer caracteres de espaço em branco IFS adjacentes, delimita um campo. Uma sequência de caracteres de espaço em branco do IFS também é tratada como um delimitador.
Para superar esse "recurso", você poderia fazer algo como o seguinte:
#!/bin/bash
DATA1="Andreas Sweden 27"
DATA2="JohnDoe 30" # <---- THERE ARE TWO TABS HERE
echo "$DATA2" | sed 's/\t/;/g' | while IFS=';' read -r NAME COUNTRY AGE; do echo "NAME: $NAME"
echo "COUNTRY: $COUNTRY" echo "AGE: $AGE"
done