GNU/Linux >> Tutoriales Linux >  >> Linux

En `while Ifs=Read..`, ¿por qué Ifs no tiene efecto?

Puede que tenga algo absolutamente incorrecto, pero me parece convincente que configurar IFS como uno de los comandos en la lista pre-do/done no tiene absolutamente ningún efecto.
El IFS externo (fuera del while constructo) prevalece en todos los ejemplos que se muestran en el siguiente script..

¿Que está pasando aqui? ¿Tengo una idea equivocada de lo que hace IFS en esta situación? Esperaba que los resultados de la división de matriz fueran los que se muestran en la columna "esperado".

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

Salida:

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

Respuesta aceptada:

(Lo siento, larga explicación)

Sí, el IFS variable en while IFS=" " read; do … no tiene efecto en el resto del código.

Relacionado:¿Leer información dentro del PDF?

Precisemos primero que la línea de comando de shell presenta dos tipos diferentes de variables:

  • variables de shell (que solo existen dentro de un shell y son locales para el shell)
  • variables de entorno, que existen para cada proceso. Esos generalmente se conservan en fork() y exec() , por lo que los procesos secundarios los heredan.

Cuando llamas a un comando con:

  A=foo B=bar command

el comando se ejecuta dentro de un entorno donde (entorno) variable A se establece en foo y B se establece en bar . Pero con esta línea de comando, las variables de shell actuales A y B se dejan sin cambios .

Esto es diferente de:

A=foo; B=bar; command

Aquí, las variables de shell A y B están definidos y el comando se ejecuta sin variables de entorno A y B definido. Valores de A y B no son accesibles desde command .

Sin embargo, si algunas variables de shell son export -ed, las variables de entorno correspondientes se sincronizan con sus respectivas variables de shell. Ejemplo:

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

Con este código, ambos shell variables y el shell entorno las variables se establecen en foo y bar . Dado que las variables de entorno son heredadas por subprocesos, command podrá acceder a sus valores.

Para regresar a su pregunta original, en:

IFS='a' read

solo read Es afectado. Y de hecho, en este caso, read no le importa el valor del IFS variable. Utiliza IFS solo cuando solicita que la línea se divida (y se almacene en varias variables), como en:

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

IFS no es utilizado por read a menos que se llame con argumentos. (Editar: Esto no es exactamente cierto:los caracteres de espacio en blanco, es decir, espacio y tabulación, presentes en IFS siempre se ignoran al principio/final de la línea de entrada. )


Linux
  1. ¿Por qué `md5sum` no da el mismo hash que Internet?

  2. Linux:¿Ionice no tiene ningún efecto en las escrituras no sincronizadas (es decir, escrituras normales)?

  3. ¿Por qué `exit &` no funciona?

  4. ¿Python tiene un argumento argc?

  5. ¿Por qué bifurcar mi proceso hace que el archivo se lea infinitamente?

¿Qué hace Echo $? ¿¿Hacer??

¿Por qué '/' tiene una entrada '..'?

¿Python tiene sincronización?

Al configurar IFS para que se divida en saltos de línea, ¿por qué es necesario incluir un retroceso?

¿Por qué pvremove tiene una fuerza duplicada en la página de manual?

¿Qué hace echo $? ¿hacer?