O que é o 'IFS'?

17

Eu estava lendo este tópico: Como fazer um loop sobre as linhas de um arquivo?

O que é IFS ? E qual é o seu uso no contexto de for -loops?

    
por chrisjlee 06.07.2011 / 22:30

4 respostas

15

IFS significa Input Internal Field Separator - é um caractere que separa os campos. No exemplo que você postou, está definido como novo caractere de linha ( \n ); assim, depois de configurá-lo, for processará o texto linha por linha. Nesse exemplo, você poderia alterar o valor de IFS (para alguma letra que você tem em seu arquivo de entrada) e verificar como o texto será dividido.

BTW, a partir da resposta que você postou a segunda solução é que recomendado ...

Como @jasonwryan notou, não é Input mas Internal . O nome Input veio de awk , no qual também há OFS - Output Field Separator .

    
por 06.07.2011 / 22:51
26

IFS não está diretamente relacionado ao loop, está relacionado à divisão de palavras. IFS indiretamente determina como a saída do comando é dividida em partes que o loop itera.

Quando você tem uma substituição de variável desprotegida $foo ou substituição de comando $(foo) , existem dois casos:

  • Se o contexto espera uma única palavra, por ex. quando a substituição estiver entre aspas duplas "$foo" ou em uma atribuição de variável x=$foo , a sequência resultante da substituição será usada como é.
  • Se o contexto espera várias palavras, o que é o caso na maioria das vezes, duas expansões adicionais são executadas na cadeia resultante:
    • A string dividida em palavras . Qualquer caractere exibido em $IFS é considerado um separador de palavras. Por exemplo, IFS=":"; foo="12:34::78"; echo $foo imprime 12 34 ​ 78 (com dois espaços entre 34 e 78 , pois há uma palavra vazia).
    • Cada palavra é tratada como um padrão glob e expandida em uma lista de nomes de arquivos . Por exemplo, foo="*"; echo $foo imprime a lista de arquivos no diretório atual.

Para loops, como muitos outros contextos, espere uma lista de palavras. Então

for x in $(foo); do …

divide $(foo) em palavras e trata cada palavra como um padrão glob. O valor padrão de IFS é espaço, guia e nova linha , portanto, se foo imprime duas linhas hello world e howdy , em seguida, o corpo do loop é executado com x=hello e, em seguida, x=world e x=howdy . Se IFS for explicitamente alterado para conter apenas uma nova linha, o loop será executado para hello world e howdy . Se IFS for alterado para o , o loop será executado para hell , ​ w , rld​␤h (onde ​␤ é um caractere de nova linha) e wdy .

    
por 06.07.2011 / 23:11
5

De man bash

IFS The Internal Field Separator that is used for word splitting after expansion and to split lines into words with the read builtin command. The default value is "<space><tab><newline>".

Esta é uma das variáveis internas do Bash. Ele determina como o Bash reconhece campos ou limites de palavras quando interpreta cadeias de caracteres.

Embora o padrão seja o espaço em branco (espaço, tabulação e nova linha), ele pode ser alterado, por exemplo, para analisar um arquivo de dados separados por vírgula.

link

    
por 06.07.2011 / 22:53
0

Além das ótimas respostas anteriores, deixe-me acrescentar que o IFS é muito útil para análise eficiente e portátil em casos simples em combinação com o conjunto . Eficiente, porque evita o uso de subshells e ferramentas de desova como grep ou 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

Basta observar que precisamos armazenar e recuperar o valor anterior de IFS para evitar quebras indesejadas em outras partes do script.

    
por 29.12.2017 / 12:29

Tags