Wie kann ich verhindern, dass "Lesen" mit "IFS" Leerzeichen zusammenführt? [Duplikat]
Nehmen Sie diesen Code, der Daten einliest, die durch getrennt sind |
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"
AUSGABE:
NAME: JohnDoe
LAND: ALTER
: 30
Es sollte identisch mit diesem Code funktionieren , bei dem wir genau das Gleiche tun und nur \t
als Trennzeichen verwenden|
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"
Aber das tut es nicht.
AUSGABE:
NAME: JohnDoe
LAND: 30 ALTER
:
Bash oder read
oder IFS
oder ein anderer Teil des Codes sperrt das Leerzeichen zusammen, wenn dies nicht beabsichtigt ist. Warum passiert das und wie kann ich es beheben?
Antworten
bash
verhält sich genau so, wie es sollte. Aus der bash
Dokumentation:
Die Shell behandelt jedes Zeichen von IFS als Trennzeichen und teilt die Ergebnisse der anderen Erweiterungen in Wörter auf diesen Zeichen auf. Wenn IFS ungesetzt ist, oder dessen Wert genau
<space><tab><newline>
der Standard, dann Sequenzen<space>
,<tab>
und<newline>
am Anfang und Ende der Ergebnisse der vorherigen Erweiterungen werden ignoriert, und jede Folge von IFS-Zeichen, die nicht am Anfang oder Ende steht, dient zur Abgrenzung von Wörtern. Wenn IFS einen anderen Wert als den Standardwert hat, werden Sequenzen des Leerzeichenzeichens und der Registerkarte am Anfang und Ende des Wortes ignoriert, solange das Leerzeichen den Wert von IFS (ein IFS-Leerzeichen) hat. Jedes Zeichen in IFS, das kein IFS-Leerzeichen ist, sowie alle benachbarten IFS-Leerzeichen setzen ein Feld. Eine Folge von IFS-Leerzeichen wird ebenfalls als Trennzeichen behandelt.
Um diese "Funktion" zu überwinden, können Sie Folgendes tun:
#!/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