GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Warum hat Ifs in `while Ifs=Read..` keine Auswirkung?

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.

Verwandte:Informationen in PDF lesen?

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 und exec() , 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. )


Linux
  1. Warum ist Printf besser als Echo?

  2. Warum wird `while Ifs=Read` so oft verwendet, anstatt `ifs=; Während Read..`?

  3. Wenns verstehen?

  4. Was bedeutet Echo $? Tun??

  5. Warum funktioniert `exit &` nicht?

Hat Curl eine Zeitüberschreitung?

Hat Python eine Synchronisierung?

Was ist eine Matrox-GPU und warum hat der UNIX-Server meiner Universität eine?

Warum zeigt mein System nur 3,2 GiB RAM an, wenn ich definitiv 4,0 GiB habe

Warum hat pvremove eine doppelte Force in der Manpage?

Was bedeutet echo $? tun?