O que é o 'IFS'?

Respostas:

17

IFSsignifica - é um caractere que separa os campos. No exemplo que você postou, ele está definido como novo caractere de linha ( ); então, depois que você o definir, processará o texto linha por linha. Nesse exemplo, você pode alterar o valor de (para alguma letra existente em seu arquivo de entrada) e verificar como o texto será dividido.Input Internal Field Separator\nforIFS

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

Como @jasonwryan notou, não é InputInternal. O nome Inputveio do awkqual também há OFS- Output Field Separator.

pbm
fonte
11
Observe que o IFS também é usado para combinar parâmetros para saída. Na página do manual do bash: "Quando a expansão ocorre entre aspas duplas, ela se expande para uma única palavra com o valor de cada parâmetro separado pelo primeiro caractere da variável especial IFS".
Eric
Deve-se notar também que while Sfoi para separador na concha Bourne de onde se originou. No shell Korn e na maioria dos outros shell tipo Bourne, como agora especificado por POSIX, o Sé para Delimiter (apenas estique um pouco sua imaginação), como A::B:por exemplo, é dividido em "A", "" e "B" (sem acréscimo adicional) ""). Isso é diferente de awk's FSou a sbandeira de expansão de parâmetros de zsh.
Stéphane Chazelas
27

IFSnão está diretamente relacionado ao loop, está relacionado à divisão de palavras. IFSdetermina indiretamente como a saída do comando é dividida em partes sobre as quais o loop é repetido.

Quando você tem uma substituição de variável não protegida $fooou substituição de comando $(foo), há dois casos:

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

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

for x in $(foo); do 

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

Gilles 'SO- parar de ser mau'
fonte
Por que você mencionou "Indiretamente" em "IFS indirectly determines how ..."?
28518
11
@ αғsнιη IFS(diretamente) determina como a saída da substituição de comando é dividida, que então (indiretamente) determina o que o loop passa.
Gilles 'SO- stop be evil'
5

A partir de man bash

IFS O Separador de Campo Interno usado para divisão de palavras após a expansão e para dividir linhas em palavras com o comando read builtin. O valor padrão é "<espaço> <guia> <nova linha>".

Essa é uma das variáveis ​​internas do Bash. Ele determina como o Bash reconhece campos ou limites de palavras quando interpreta seqüências de caracteres.

Embora o padrão seja 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.

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

jasonwryan
fonte
0

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

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

pmod
fonte