Wie kann ich verhindern, dass "Lesen" mit "IFS" Leerzeichen zusammenführt? [Duplikat]

Nov 26 2020

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 \tals 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 readoder IFSoder ein anderer Teil des Codes sperrt das Leerzeichen zusammen, wenn dies nicht beabsichtigt ist. Warum passiert das und wie kann ich es beheben?

Antworten

3 fpmurphy Nov 26 2020 at 11:00

bashverhält sich genau so, wie es sollte. Aus der bashDokumentation:

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