Was ist das IFS?

Antworten:

17

IFSsteht für - es ist ein Zeichen, das Felder trennt. In dem Beispiel, das Sie gepostet haben, ist es auf das Zeichen für eine neue Zeile ( ) gesetzt. Nachdem Sie dies eingestellt haben, wird der Text zeilenweise verarbeitet. In diesem Beispiel können Sie den Wert von (in einen Buchstaben, den Sie in Ihrer Eingabedatei haben) ändern und prüfen, wie der Text aufgeteilt wird.Input Internal Field Separator\nforIFS

Übrigens, von der Antwort, die Sie gepostet haben, ist die zweite Lösung die empfohlene ...

Wie @jasonwryan bemerkt hat, ist es nicht Inputaber Internal. Name Inputkam von awkdem es auch OFS- gibt Output Field Separator.

pbm
quelle
1
Beachten Sie, dass IFS auch zum Kombinieren von Parametern für die Ausgabe verwendet wird. Aus der Bash-Manpage: "Wenn die Erweiterung in doppelten Anführungszeichen erfolgt, wird sie zu einem einzelnen Wort erweitert, wobei der Wert jedes Parameters durch das erste Zeichen der IFS-Sondervariable getrennt wird."
Eric
Man sollte auch beachten, dass while Sfür separator in der Bourne-Shell war, woher es stammt. In der Korn-Shell und den meisten anderen Bourne-ähnlichen Shells, wie sie jetzt von spezifiziert wurden POSIX, ist der Sis for Delimiter (erweitern Sie einfach Ihre Vorstellungskraft), da A::B:er beispielsweise in "A", "" und "B" aufgeteilt ist (ohne Extrakosten) ""). Das unterscheidet sich von awk's FSoder der sParametererweiterung von zsh.
Stéphane Chazelas
27

IFSist nicht direkt mit dem Schleifen verbunden, sondern mit dem Teilen von Wörtern. IFSLegt indirekt fest, wie die Ausgabe des Befehls in Teile aufgeteilt wird, über die die Schleife iteriert.

Wenn Sie eine ungeschützte Variablensubstitution $foooder Befehlssubstitution haben $(foo), gibt es zwei Fälle:

  • Wenn der Kontext ein einzelnes Wort erwartet, z. B. wenn die Ersetzung zwischen doppelten Anführungszeichen "$foo"oder in einer variablen Zuweisung erfolgt x=$foo, wird der aus der Ersetzung resultierende String unverändert verwendet.
  • Wenn der Kontext mehrere Wörter erwartet, was meistens der Fall ist, werden zwei weitere Erweiterungen an der resultierenden Zeichenfolge durchgeführt:
    • Die Zeichenfolge ist in Wörter aufgeteilt . Jedes Zeichen, das in angezeigt $IFSwird, wird als Worttrennzeichen betrachtet. Zum Beispiel IFS=":"; foo="12:34::78"; echo $fooAusdrucke 12 34 ​ 78(mit zwei Leerzeichen zwischen 34und 78, da es ein leeres Wort gibt).
    • Jedes Wort wird als Glob-Muster behandelt und zu einer Liste von Dateinamen erweitert . Druckt beispielsweise foo="*"; echo $foodie Liste der Dateien im aktuellen Verzeichnis.

Erwarten Sie für Schleifen wie für viele andere Kontexte eine Liste von Wörtern. So

for x in $(foo); do 

zerbricht $(foo)in Wörter und behandelt jedes Wort als Glob-Muster. Der Standardwert von IFSist space, tab und newline . Wenn also foozwei Zeilen ausgedruckt werden hello worldund howdydann der Schleifenkörper mit x=hello, dann x=worldund ausgeführt wird x=howdy. Wenn IFSexplizit geändert wird, um nur eine neue Zeile zu enthalten, wird die Schleife für hello worldund ausgeführt howdy. Wenn IFSgeändert zu werden o, dann wird die Schleife für ausgeführt hell, ​ w, rld​␤h(wobei ​␤ein Zeilenendezeichen) , und wdy.

Gilles 'SO - hör auf böse zu sein'
quelle
Warum haben Sie in "Indirekt" erwähnt "IFS indirectly determines how ..."?
αғsнιη
1
@ αғsнιη IFS(direkt) bestimmt, wie die Ausgabe der Befehlssubstitution aufgeteilt wird, die dann (indirekt) bestimmt, worüber die Schleife durchläuft.
Gilles 'SO- hör auf böse zu sein'
5

Von man bash

IFS Das interne Feldtrennzeichen, das zum Teilen von Wörtern nach der Erweiterung und zum Teilen von Zeilen in Wörter mit dem Befehl read builtin verwendet wird. Der Standardwert ist "<Leerzeichen> <Tab> <Zeilenvorschub>".

Dies ist eine der internen Variablen von Bash. Es legt fest, wie Bash Felder oder Wortgrenzen erkennt, wenn Zeichenfolgen interpretiert werden.

Die Standardeinstellung ist Leerzeichen (Leerzeichen, Tabulator und Zeilenvorschub). Sie kann jedoch geändert werden, um beispielsweise eine durch Kommas getrennte Datendatei zu analysieren.

http://tldp.org/LDP/abs/html/internalvariables.html

jasonwryan
quelle
0

Lassen Sie mich zusätzlich zu den bisherigen tollen Antworten hinzufügen, dass IFS in Kombination mit set in einfachen Fällen sehr nützlich für effizientes und portables Parsen ist . Effizient, da die Verwendung von Subshells und Laichwerkzeugen wie grep oder sed vermieden wird:

resolutions="640x480,320x240"
xIFS=$IFS
IFS=','
for res in $resolutions; do
    xxIFS=$IFS
    IFS='x'
    set -- $res
    width=$1
    height=$2
    # handle width and height
    IFS=$xxIFS
done;
IFS=$xIFS

Beachten Sie nur, dass wir den vorherigen Wert von IFS speichern und wiederherstellen müssen , um unerwünschte Brüche in anderen Teilen des Skripts zu vermeiden.

pmod
quelle