Comment puis-je empêcher «read» avec «IFS» de fusionner des caractères d'espaces? [dupliquer]
Prenez ce morceau de code qui lit les données séparées par |
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"
PRODUCTION:
NOM: JohnDoe
PAYS:
ÂGE: 30
Cela devrait fonctionner de la même manière que ce morceau de code, où nous faisons exactement la même chose, en utilisant simplement \tcomme séparateur au lieu 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"
Mais ce n'est pas le cas.
PRODUCTION:
NOM: JohnDoe
PAYS: 30
ÂGE:
Bash, ou readou IFSou une autre partie du code est en train de regrouper l'espace blanc alors que ce n'est pas censé le faire. Pourquoi cela se produit-il et comment puis-je y remédier?
Réponses
bashse comporte exactement comme il se doit. De la bashdocumentation:
Le shell traite chaque caractère d'IFS comme un délimiteur et divise les résultats des autres extensions en mots sur ces caractères. Si IFS est inexistante, ou sa valeur est exactement
<space><tab><newline>, la valeur par défaut, puis des séquences de<space>,<tab>et<newline>au début et à la fin des résultats des extensions précédentes sont ignorés, et toute séquence de caractères IFS qui ne se trouve pas au début ou à la fin sert à délimiter les mots. Si IFS a une valeur autre que la valeur par défaut, alors les séquences d'espaces et de tabulations sont ignorées au début et à la fin du mot, tant que le caractère d'espacement a la valeur IFS (un caractère d'espacement IFS). Tout caractère IFS qui n'est pas un espace IFS, ainsi que tout caractère d'espacement IFS adjacent, délimite un champ. Une séquence de caractères d'espaces IFS est également traitée comme un délimiteur.
Pour surmonter cette "fonctionnalité", vous pouvez faire quelque chose comme ceci:
#!/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