понимание значения по умолчанию IFS


10

В моей версии GNU bash 4.2.8 IFS по умолчанию имеет значение пробела, табуляции и перевода строки:

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

Есть ли причина для такого дефолта IFS? Кроме того, какие утилиты используют IFS помимо встроенного bash read?

Ответы:


13

Переменная IFS используется каждый раз, когда оболочка выполняет задачу, называемую разделением слов . Наиболее распространенные случаи, когда это используется, - это расширение параметра (например, $var) или подстановка команды (например, $(some-command)или устаревшие обратные ссылки) в команде. Здесь, если расширение содержит какие-либо IFSсимволы, то перед обработкой команды оно разделяется на разные «слова». Фактически это означает, что эти символы разделяют замещенный текст на разные аргументы (включая имя команды, если переменная указана первой).

Таким образом, причина значения по умолчанию IFSпробела, табуляции и перехода на новую строку заключается в том, что это пробельные символы, которые обычно должны разделять слово.

Один из способов предотвратить расщепление слов - использовать двойные кавычки вокруг расширения ( "$var") - фактически, вы сделали это в своем вопросе. Если вы этого не сделаете, не будет никакого вывода, так echoкак у него не будет аргументов, только символы, разделяющие аргументы.

Также обратите внимание, что два места, где разделение слов не происходит после раскрытия параметра, - с присвоением переменной (например, var=$othervarи var=$(somecommand)в порядке) и внутри [[ ]]конструкции ( [[ $var = $othervar ]]в порядке, но [ $var = $othervar ]следует заключать в кавычки).

Наконец, как однажды сказал мне один мудрец, распространенное заблуждение состоит в том, что предотвращение разбиения слов является единственной причиной для цитирования переменной. Это не так, цитирование также предотвращает расширение имени пути или расширение глобуса, как это более широко известно. Если переменная содержит подобные символы глобуса, *то они могут быть расширены до имен файлов, когда переменная используется без кавычек в команде. Например, рассмотрим:

var=*
echo $var

Это отобразит имена файлов в текущем каталоге.

Как указывает Стефан ниже , IFSпри расширении важен порядок символов внутри "$*". Со bashстраницы руководства :

"$*" 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.

Дополнительные примеры разбиения слов приведены в этом ответе - https://unix.stackexchange.com/a/118444/48083.


1
Первый символ $IFSтакже используется "$*", поэтому порядок имеет значение.
Стефан Шазелас

2
Также обратите внимание, что zshв его значение по умолчанию входит символ NUL $IFS(другие оболочки не поддерживают удерживание символа NUL в своих переменных).
Стефан Шазелас
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.