Ich könnte etwas absolut falsch haben, aber es scheint mir überzeugend, IFS als einen der Befehle festzulegen in der Pre-Do/Done-Liste hat absolut keine Auswirkung.
Das äußere IFS (außerhalb des while
Konstrukt) hat in allen Beispielen Vorrang, die im folgenden Skript gezeigt werden..
Was ist denn hier los? Habe ich eine falsche Vorstellung davon, was IFS in dieser Situation tut? Ich habe erwartet, dass die Array-Split-Ergebnisse wie in der Spalte „erwartet“ angezeigt werden.
#!/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=$' tn'; xifs "$IFS"; echo "$data" | while read; do echo -ne 't 1'; show "$REPLY"; done
IFS=$' tn'; xifs "$IFS"; echo "$data" | while IFS= read; do echo -ne 't 2'; show "$REPLY"; done
IFS=$' tn'; 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=" "
----- -- -- -------- ----- --------- -------
Akzeptierte Antwort:
(Sorry, lange Erklärung)
Ja, das IFS
Variable in while IFS=" " read; do …
hat keine Auswirkung auf den Rest des Codes.
Lassen Sie uns zunächst präzisieren, dass die Shell-Befehlszeile zwei verschiedene Arten von Variablen enthält:
- Shell-Variablen (die nur innerhalb einer Shell existieren und für die Shell lokal sind)
- Umgebungsvariablen, die für jeden Prozess existieren. Diese werden normalerweise bei
fork()
beibehalten undexec()
, also erben untergeordnete Prozesse sie.
Wenn Sie einen Befehl aufrufen mit:
A=foo B=bar command
Der Befehl wird in einer Umgebung ausgeführt, in der die (Umgebungs-)Variable A
auf foo
gesetzt ist und B
auf bar
eingestellt ist . Aber mit dieser Befehlszeile werden die aktuellen Shell-Variablen A
und B
werden unverändert gelassen .
Dies unterscheidet sich von:
A=foo; B=bar; command
Hier Shell-Variablen A
und B
definiert sind und der Befehl ohne Umgebungsvariablen A
ausgeführt wird und B
definiert. Werte von A
und B
sind über command
nicht zugänglich .
Wenn jedoch einige Shell-Variablen export
sind -ed werden die entsprechenden Umgebungsvariablen mit ihren jeweiligen Shell-Variablen synchronisiert. Beispiel:
export A
export B
A=foo; B=bar; command
Mit diesem Code können beide shell Variablen und die Umgebung der Shell Variablen werden auf foo
gesetzt und bar
. Da Umgebungsvariablen von Unterprozessen geerbt werden, ist command
auf ihre Werte zugreifen können.
Um zu Ihrer ursprünglichen Frage zurückzukehren, in:
IFS='a' read
nur read
ist betroffen. Und in diesem Fall sogar read
kümmert sich nicht um den Wert von IFS
Variable. Es verwendet IFS
nur wenn Sie fragen, ob die Zeile geteilt (und in mehreren Variablen gespeichert) werden soll, wie in:
echo "a : b : c" | IFS=":" read i j k;
printf "i is '%s', j is '%s', k is '%s'" "$i" "$j" "$k"
IFS
wird von read
nicht verwendet es sei denn, es wird mit Argumenten aufgerufen. (Bearbeiten: Das ist nicht ganz richtig:Whitespace-Zeichen, d. h. Leerzeichen und Tabulatoren, sind in IFS
vorhanden werden am Anfang/Ende der Eingabezeile immer ignoriert. )