Comprender el valor predeterminado de IFS

10

En mi GNU bash versión 4.2.8, IFS tiene un valor predeterminado de espacio, tabulación y avance de línea por defecto:

usr@T42 ~ $ echo -n "$IFS" | hexdump -C
00000000  20 09 0a                                          | ..|
00000003
usr@T42 ~ $ 

¿Hay alguna razón para tal IFS predeterminado? Además, ¿qué utilidades usan IFS además de bash incorporado read?

Martín
fuente

Respuestas:

13

La variable IFS se usa cada vez que el shell realiza una tarea llamada división de palabras . Los casos más comunes en los que se usa esto son después de la expansión de parámetros (p $var. Ej. ) O la sustitución de comandos (p. Ej., $(some-command)O los backticks obsoletos) en un comando. Aquí, si la expansión contiene IFScaracteres, se divide en diferentes 'palabras' antes de que se procese el comando. Efectivamente, esto significa que estos caracteres dividen el texto sustituido en diferentes argumentos (incluido el nombre del comando si la variable se especifica primero).

Por lo tanto, la razón del valor predeterminado de IFSser espacio, tabulación y nueva línea es que estos son los caracteres de espacio en blanco que normalmente se esperaría para dividir una palabra.

Una forma de evitar que se divida la palabra es usar comillas dobles alrededor de la expansión ( "$var"); de hecho, lo ha hecho en su pregunta. Si no hiciera esto, no habría salida echoya que no tendría argumentos, solo caracteres que dividirían argumentos.

Tenga en cuenta también que dos lugares donde la división de palabras no ocurre después de la expansión de parámetros son con asignación de variable (por ejemplo, var=$othervary var=$(somecommand)está bien), y dentro de la [[ ]]construcción ( [[ $var = $othervar ]]está bien, pero [ $var = $othervar ]debe citarse).

Finalmente, como un hombre sabio me señaló una vez, un error común es que la prevención de la división de palabras es la única razón para citar una variable. No lo es, la cita también evita la expansión del nombre de ruta o la expansión global, como se conoce más comúnmente. Si una variable contiene caracteres globales como *estos, estos pueden expandirse a nombres de archivo cuando la variable se usa sin comillas en un comando. Por ejemplo, considere:

var=*
echo $var

Esto mostrará los nombres de los archivos en el directorio actual.

Como Stephane señala a continuación , el orden de los caracteres dentro IFSes significativo cuando se expande "$*". Desde la bashpágina del manual:

"$*" is equivalent to "$1c$2c...", where c is the first character of the value of
the IFS variable.  If IFS is unset, the parameters are separated by spaces.  If
IFS is null, the parameters are joined without intervening separators.

Para obtener más ejemplos de división de palabras, consulte esta respuesta: https://unix.stackexchange.com/a/118444/48083

Graeme
fuente
1
$IFSTambién se usa el primer carácter de, "$*"por lo que el orden es importante.
Stéphane Chazelas
2
También tenga en cuenta que zshincluye el carácter NUL en su valor predeterminado $IFS(otros shells no admiten mantener el carácter NUL en sus variables).
Stéphane Chazelas