GNU/Linux >> Tutoriels Linux >  >> Linux

Dans `while Ifs=Read..`, Pourquoi Ifs n'a-t-il aucun effet ?

J'ai peut-être quelque chose d'absolument faux, mais cela me semble convaincant, que définir IFS comme l'une des commandes dans la liste pre-do/done n'a absolument aucun effet.
L'IFS externe (en dehors du while construct) prévaut dans tous les exemples présentés dans le script ci-dessous.

Que se passe t-il ici? Ai-je une mauvaise idée de ce que fait IFS dans cette situation ? Je m'attendais à ce que les résultats de la division du tableau soient comme indiqué dans la colonne "attendu".

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

Sortie :

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

Réponse acceptée :

(Désolé, longue explication)

Oui, l'IFS variable dans while IFS=" " read; do … n'a aucun effet sur le reste du code.

En relation :Lire les informations dans le PDF ?

Précisons d'abord que la ligne de commande du shell comporte deux types de variables différents :

  • variables shell (qui n'existent que dans un shell et sont locales au shell)
  • variables d'environnement, qui existent pour chaque processus. Ceux-ci sont généralement conservés sur fork() et exec() , donc les processus enfants en héritent.

Lorsque vous appelez une commande avec :

  A=foo B=bar command

la commande est exécutée dans un environnement où la variable (d'environnement) A est défini sur foo et B est défini sur bar . Mais avec cette ligne de commande, les variables shell actuelles A et B sont laissés inchangés .

Ceci est différent de :

A=foo; B=bar; command

Ici, les variables shell A et B sont définis et la commande est exécutée sans les variables d'environnement A et B défini. Valeurs de A et B sont inaccessibles depuis la command .

Cependant, si certaines variables shell sont export -ed, les variables d'environnement correspondantes sont synchronisées avec leurs variables shell respectives. Exemple :

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

Avec ce code, les deux shell les variables et l'environnement shell les variables sont définies sur foo et bar . Puisque les variables d'environnement sont héritées par les sous-processus, command pourront accéder à leurs valeurs.

Pour revenir à votre question initiale, dans :

IFS='a' read

seulement read est affectée. Et en fait, dans ce cas, read ne se soucie pas de la valeur de l'IFS variable. Il utilise IFS uniquement lorsque vous demandez à la ligne d'être scindée (et stockée dans plusieurs variables), comme dans :

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

IFS n'est pas utilisé par read sauf s'il est appelé avec des arguments. (Modifier : Ce n'est pas tout à fait vrai :les caractères d'espacement, c'est-à-dire l'espace et la tabulation, sont présents dans IFS sont toujours ignorés au début/à la fin de la ligne d'entrée. )


Linux
  1. Pourquoi Printf est-il meilleur qu'Echo ?

  2. Pourquoi `while Ifs=Read` est-il utilisé si souvent, au lieu de `ifs=; Pendant la lecture..` ?

  3. Comprendre les Si ?

  4. Pourquoi un nouveau répertoire a-t-il un nombre de liens physiques de 2 avant que quoi que ce soit ne soit ajouté ?

  5. Pourquoi `md5sum` ne donne-t-il pas le même hachage qu'Internet ?

Linux - Ionice n'a aucun effet sur les écritures non synchronisées (c'est-à-dire les écritures normales) ?

Pourquoi la bifurcation de mon processus entraîne-t-elle la lecture infinie du fichier

Qu'est-ce qu'un GPU Matrox et pourquoi le serveur UNIX de mon université en a-t-il un ?

Pourquoi mon système n'affiche-t-il que 3,2 Go de RAM alors que j'ai définitivement 4,0 Go

Pourquoi pvremove a-t-il une force en double dans la page de manuel ?

Qu'est-ce que echo $ ? fais?