GNU/Linux >> Znalost Linux >  >> Linux

Proč nemají Ifs žádný účinek v `když Ifs=číst...`?

Možná mám něco úplně špatně, ale zdá se mi přesvědčivé, že nastavení IFS jako jednoho z příkazů v seznamu pre-do/done nemá absolutně žádný vliv.
Vnější IFS (mimo while konstrukt) převládá ve všech příkladech zobrazených ve skriptu níže..

Co se tam děje? Mám špatnou představu o tom, co IFS v této situaci dělá? Očekával jsem, že výsledky rozdělení pole budou takové, jaké jsou uvedeny ve sloupci „očekávané“.

#!/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-----"

Výstup:

-----   --  --   --------       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=" "
-----   --  --   --------       -----      ---------   -------                        

Přijatá odpověď:

(Omlouvám se, dlouhé vysvětlení)

Ano, IFS proměnná v while IFS=" " read; do … nemá žádný vliv na zbytek kódu.

Související:Číst informace v PDF?

Nejprve upřesněme, že příkazový řádek shellu obsahuje dva různé druhy proměnných:

  • proměnné shellu (které existují pouze v rámci shellu a jsou lokální pro shell)
  • proměnné prostředí, které existují pro každý proces. Ty jsou obvykle zachovány na fork() a exec() , takže je podřízené procesy zdědí.

Když zavoláte příkaz pomocí:

  A=foo B=bar command

příkaz se provádí v prostředí, kde (prostředí) proměnná A je nastaveno na foo a B je nastavena na bar . Ale s tímto příkazovým řádkem jsou aktuální proměnné shellu A a B jsou ponechány beze změny .

To se liší od:

A=foo; B=bar; command

Zde shellové proměnné A a B jsou definovány a příkaz je spuštěn bez proměnných prostředí A a B definována. Hodnoty A a B jsou nepřístupné z command .

Pokud jsou však některé proměnné shellu export -ed, odpovídající proměnné prostředí jsou synchronizovány s jejich příslušnými proměnnými prostředí. Příklad:

export A
export B
A=foo; B=bar; command

S tímto kódem se oba skryjí proměnné a prostředí shellu proměnné jsou nastaveny na foo a bar . Protože proměnné prostředí dědí dílčí procesy, command budou mít přístup k jejich hodnotám.

Chcete-li se vrátit k původní otázce, v:

IFS='a' read

pouze read je ovlivněna. A ve skutečnosti v tomto případě read nezajímá se o hodnotu IFS variabilní. Používá IFS pouze když požádáte o rozdělení řádku (a uložení do několika proměnných), jako v:

echo "a :  b :    c" | IFS=":" read i j k; 
    printf "i is '%s', j is '%s', k is '%s'" "$i" "$j" "$k"

IFS read nepoužívá pokud není volána s argumenty. (Upravit: Není to tak úplně pravda:mezery, tj. mezera a tabulátor, jsou v IFS jsou vždy ignorovány na začátku/konci vstupního řádku. )


Linux
  1. Má Curl časový limit?

  2. Co dělá Echo $? Dělat??

  3. Proč má „/“ položku „...“?

  1. Proč je Printf lepší než Echo?

  2. Proč má pvremove v manuálové stránce duplicitní sílu?

  3. Co znamená echo $? dělat?

  1. Proč se `při Ifs=Read` tak často používá místo `ifs=; Při čtení..`?

  2. Rozumět Ifs?

  3. Proč má nový adresář počet pevných odkazů 2, než se do něj něco přidá?