¿Qué es el 'IFS'?

Respuestas:

17

IFSsignifica : es un personaje que separa los campos. En el ejemplo que publicó, se establece en un nuevo carácter de línea ( ); así que después de configurarlo, procesará el texto línea por línea. En ese ejemplo, podría cambiar el valor de (a alguna letra que tenga en su archivo de entrada) y verificar cómo se dividirá el texto.Input Internal Field Separator\nforIFS

Por cierto, de la respuesta que publicó la segunda solución es que se recomienda ...

Como @jasonwryan notó, no es Inputsino Internal. Nombre de donde Inputproviene awktambién OFS- Output Field Separator.

pbm
fuente
1
Tenga en cuenta que IFS también se utiliza para combinar parámetros de salida. Desde la página de manual de bash: "Cuando la expansión se produce entre comillas dobles, se expande a una sola palabra con el valor de cada parámetro separado por el primer carácter de la variable especial IFS".
Eric
También se debe tener en cuenta que while Sfue para el separador en el shell Bourne de donde se originó. En el shell Korn y en la mayoría de los otros shell similares a Bourne, como se ha especificado ahora POSIX, Ses para Delimitador (solo estira tu imaginación un poco) ya que, A::B:por ejemplo, se divide en "A", "" y "B" (sin extra ""). Eso es diferente de awk's FSo la sbandera de expansión de parámetros de zsh.
Stéphane Chazelas
27

IFSno está directamente relacionado con el bucle, está relacionado con la división de palabras. IFSdetermina indirectamente cómo la salida del comando se divide en partes sobre las que el ciclo itera.

Cuando tiene una sustitución de variable desprotegida $fooo una sustitución de comando $(foo), hay dos casos:

  • Si el contexto espera una sola palabra, por ejemplo, cuando la sustitución se realiza entre comillas dobles "$foo"o en una asignación variable x=$foo, la cadena resultante de la sustitución se utiliza tal cual.
  • Si el contexto espera varias palabras, que es el caso la mayoría de las veces, se realizan dos expansiones adicionales en la cadena resultante:
    • La cadena se divide en palabras . Cualquier carácter que aparece en $IFSse considera un separador de palabras. Por ejemplo, IFS=":"; foo="12:34::78"; echo $fooimpresiones 12 34 ​ 78(con dos espacios entre 34y 78, ya que hay una palabra vacía).
    • Cada palabra se trata como un patrón global y se expande en una lista de nombres de archivo . Por ejemplo, foo="*"; echo $fooimprime la lista de archivos en el directorio actual.

Para los bucles, como muchos otros contextos, espere una lista de palabras. Entonces

for x in $(foo); do 

se divide $(foo)en palabras y trata cada palabra como un patrón global. El valor predeterminado de IFSes space, tab y newline , por lo que si fooimprime dos líneas hello worldy howdyluego el cuerpo del bucle se ejecuta con x=hello, entonces x=worldy x=howdy. Si IFSse cambia explícitamente para contener solo una nueva línea, el bucle se ejecuta para hello worldy howdy. Si IFSse cambia a ser o, entonces el bucle se ejecuta para hell, ​ w, rld​␤h(donde ​␤es un carácter de nueva línea) y wdy.

Gilles 'SO- deja de ser malvado'
fuente
¿Por qué mencionaste "indirectamente" en "IFS indirectly determines how ..."?
αғsнιη
1
@ αғsнιη IFS(directamente) determina cómo se divide la salida de la sustitución del comando, que luego (indirectamente) determina sobre qué se repite el bucle.
Gilles 'SO- deja de ser malvado'
5

Desde man bash

IFS El separador de campo interno que se usa para dividir palabras después de la expansión y para dividir líneas en palabras con el comando de lectura incorporado. El valor predeterminado es "<space> <tab> <newline>".

Esta es una de las variables internas de Bash. Determina cómo Bash reconoce campos, o límites de palabras, cuando interpreta cadenas de caracteres.

Si bien el valor predeterminado es el espacio en blanco (espacio, tabulación y nueva línea), se puede cambiar, por ejemplo, para analizar un archivo de datos separados por comas.

http://tldp.org/LDP/abs/html/internalvariables.html

jasonwryan
fuente
0

Además de las excelentes respuestas anteriores, permítanme agregar que IFS es muy útil para un análisis eficiente y portátil en casos simples en combinación con el conjunto . Eficiente, porque evita el uso de subcapas y herramientas de desove como grep o sed:

resolutions="640x480,320x240"
xIFS=$IFS
IFS=','
for res in $resolutions; do
    xxIFS=$IFS
    IFS='x'
    set -- $res
    width=$1
    height=$2
    # handle width and height
    IFS=$xxIFS
done;
IFS=$xIFS

Solo tenga en cuenta que necesitamos almacenar y recuperar el valor anterior de IFS para evitar roturas no deseadas en otras partes del script.

pmod
fuente