entendendo o valor padrão do IFS

10

Na minha versão 4.2.8 do GNU bash, o IFS possui um valor padrão de espaço, tabulação e linha de alimentação por padrão:

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

Existe uma razão para esse IFS padrão? Além disso, quais utilitários usam o IFS além do bash embutido read?

Martin
fonte

Respostas:

13

A variável IFS é usada toda vez que o shell executa uma tarefa chamada divisão de palavras . Os casos mais comuns em que isso é usado são após a expansão do parâmetro (por exemplo $var) ou substituição de comando (por exemplo, $(some-command)ou backticks obsoletos) em um comando. Aqui, se a expansão contiver algum IFScaractere, ela será dividida em diferentes 'palavras' antes do processamento do comando. Efetivamente, isso significa que esses caracteres dividem o texto substituído em argumentos diferentes (incluindo o nome do comando se a variável for especificada primeiro).

Portanto, o motivo do valor padrão de IFSespaço, tabulação e nova linha é que esses são os caracteres de espaço em branco que normalmente se espera que dividam uma palavra.

Uma maneira de impedir que a divisão de palavras aconteça é usar aspas duplas na expansão ( "$var") - na verdade, você fez isso na sua pergunta. Se você não fizesse isso, não haveria saída, echopois não haveria argumentos, apenas caracteres dividindo argumentos.

Observe também que dois lugares onde a divisão de palavras não ocorre após a expansão dos parâmetros estão com atribuição de variável (por exemplo, var=$othervare var=$(somecommand)está ok) e dentro da [[ ]]construção ( [[ $var = $othervar ]]está ok, mas [ $var = $othervar ]deve ser citado).

Finalmente, como um homem sábio uma vez me apontou, um equívoco comum é que a prevenção da divisão de palavras é a única razão para citar uma variável. Não é, a citação também evita a expansão do nome do caminho ou expansão glob, como é mais conhecido. Se uma variável contiver caracteres globos como *esses, eles poderão ser expandidos para nomes de arquivos quando a variável for usada sem aspas em um comando. Por exemplo, considere:

var=*
echo $var

Isso exibirá os nomes dos arquivos no diretório atual.

Como Stephane aponta abaixo , a ordem dos caracteres internos IFSé significativa ao expandir "$*". Na bashpágina do 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 obter mais exemplos de divisão de palavras, consulte esta resposta - https://unix.stackexchange.com/a/118444/48083

Graeme
fonte
1
O primeiro caractere de $IFStambém é usado "$*"e é por isso que a ordem é importante.
Stéphane Chazelas
2
Observe também que zshinclui o caractere NUL em seu padrão $IFS(outros shells não suportam manter o caractere NUL em suas variáveis).
Stéphane Chazelas