Что такое «IFS»?

Ответы:

17

IFSобозначает - это символ, который разделяет поля. В примере, который вы разместили, он установлен на символ новой строки ( ); поэтому после его установки текст будет обрабатываться построчно. В этом примере вы можете изменить значение (на некоторую букву, которая есть во входном файле) и проверить, как будет разделяться текст.Input Internal Field Separator\nforIFS

Кстати, из ответа вы опубликовали второе решение, которое рекомендуется ...

Как @jasonwryan заметил, что это не Inputно Internal. Название Inputпришло из awkкоторого тоже есть OFS- Output Field Separator.

постоянный репер
источник
1
Обратите внимание, что IFS также используется для объединения параметров для вывода. Со страницы руководства bash: «Когда раскрытие происходит в двойных кавычках, оно раскрывается до одного слова со значением каждого параметра, разделенного первым символом специальной переменной IFS».
Эрик
Следует также отметить, что while Sбыл для сепаратора в оболочке Bourne, откуда он произошел. В оболочке Korn и в большинстве других оболочек типа Bourne, как это было определено ранее POSIX, параметр Sis for Delimiter (просто немного напрягает воображение), A::B:например, разделен на «A», «» и «B» (без дополнительных ""). Это отличается от awk's FSили sфлага расширения параметра zsh.
Стефан
27

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

Если у вас есть незащищенная замена переменных $fooили подстановка команд $(foo), есть два случая:

  • Если контекст ожидает одно слово, например, когда подстановка находится между двойными кавычками "$foo"или в присваивании переменной x=$foo, тогда строка, полученная в результате подстановки, используется как есть.
  • Если контекст ожидает нескольких слов, что имеет место в большинстве случаев, то в результирующей строке выполняются два дополнительных раскрытия:
    • Строка разбита на слова . Любой символ, который появляется в $IFS, считается разделителем слов. Например, IFS=":"; foo="12:34::78"; echo $fooпечатает 12 34 ​ 78(с двумя пробелами между 34и 78, так как есть пустое слово).
    • Каждое слово рассматривается как шаблон глобуса и разворачивается в список имен файлов . Например, foo="*"; echo $fooпечатает список файлов в текущем каталоге.

Для циклов, как и во многих других контекстах, ожидайте список слов. Так

for x in $(foo); do 

разбивается $(foo)на слова и рассматривает каждое слово как шаблон глобуса. Значением по умолчанию IFSявляется пробел, табуляция и новаяfoo строка , поэтому, если вывести две строки, hello worldа howdyзатем выполнить тело цикла с помощью x=hello, то x=worldи x=howdy. Если IFSявно изменить только на новую строку, цикл выполняется для hello worldи howdy. Если IFSизменяется , чтобы быть o, то цикл выполняется для hell, ​ w, rld​␤h(где ​␤это символ новой строки) и wdy.

Жиль "ТАК - перестань быть злым"
источник
Почему вы упомянули «Косвенно» в "IFS indirectly determines how ..."?
августа
1
@ αғsнιη IFS(напрямую) определяет способ разбиения выходных данных подстановки команд, который затем (косвенно) определяет цикл.
Жиль "ТАК - перестань быть злым"
5

Из man bash

IFS Внутренний разделитель полей, который используется для разделения слов после раскрытия и разделения строк на слова с помощью встроенной команды read. Значением по умолчанию является «<пробел> <вкладка> <новая строка>».

Это одна из внутренних переменных Bash. Он определяет, как Bash распознает поля или границы слов при интерпретации символьных строк.

Хотя по умолчанию используется пробел (пробел, табуляция и новая строка), его можно изменить, например, для анализа файла данных, разделенных запятыми.

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

jasonwryan
источник
0

В дополнение к предыдущим отличным ответам, позвольте мне добавить, что IFS очень полезен для эффективного и переносимого анализа в простых случаях в сочетании с set . Эффективно, потому что избегает использования подоболочек и нерестильных инструментов, таких как grep или 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

Просто отметьте, что нам нужно сохранить и восстановить предыдущее значение IFS, чтобы избежать нежелательных поломок в других частях скрипта.

PMOD
источник