Ich habe vielleicht etwas absolut Falsches, aber es scheint mir überzeugend, dass das Setzen von IFS als eines der Befehle in der Pre-Do / Do-Liste absolut keine Wirkung hat.
Das äußere IFS (außerhalb des while
Konstrukts) ist in allen im folgenden Skript gezeigten Beispielen maßgeblich.
Was ist denn hier los? Habe ich eine falsche Vorstellung davon, was IFS in dieser Situation tut? Ich habe erwartet, dass die Ergebnisse der Array-Aufteilung den Angaben in der Spalte "erwartet" entsprechen.
#!/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-----"
Ausgabe:
----- -- -- -------- 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
der Eingabezeile enthalten sind, am Anfang / Ende der Eingabezeile entfernt werden, nehme ich an? (So funktioniert es.)a<tab>b
zuread var
werden in var führt mit dem Werta<space>b
, aber wenn stattdessen haben SieIFS='<newline>' read var
dann wird der Wert von var seina<tab>b
.Vereinfacht ausgedrückt müssen Sie jeweils mehrere Variablen lesen, damit das
IFS=<something> read ...
Konstrukt in Ihren Beispielen 1 einen sichtbaren Effekt hat .Sie vermissen den Umfang der
read
in den Beispielen. In Ihren Testfällen gibt es keine Änderung des IFS innerhalb der Schleife. Lassen Sie mich genau sagen, woher das zweite IFS in jeder Ihrer Zeilen kommt:Es ist wie bei jedem Programm, das in der Shell ausgeführt wird. Die Variable, die Sie in der Befehlszeile (neu) definieren, wirkt sich auf die Programmausführung aus. Und nur das (da du nicht exportierst). Um die
IFS
in einer solchen Zeile neu definierte Funktion verwenden zu können, müssen Sieread
daher mehr als einer Variablen Werte zuweisen . Schauen Sie sich diese Beispiele an:1 Wie ich gerade von Gilles erfahren habe, hat das Setzen
IFS=''
(Leerzeichen) beim Lesen nur eines Feldes möglicherweise den Vorteil, dass Leerzeichen am Anfang der Zeile nicht abgeschnitten werden.quelle
IFS= read
bevorzugt verwendet, um nur die IFS-Umgebungsvariable zurückzusetzen". Ich wusste also nicht, dass der Aufrufer eines Befehls lokale Variablen setzen kann. Das war die Antwort auf diese Frage. Es hat sich weiterentwickelt, um den Hauptpunkt dieser Frage anzusprechen, aber als mir klar wurde, dass ich diese Frage bereits gestellt hatte ... Vielleicht sind die beiden Fragen so ähnlich wie zweised
Fragen, und ich habe das Gefühl, dass es so bleibt ... Weitere Titel für Googler zu googeln.