Я читал эту ветку: Как перебрать строки файла?
Что такое IFS
? И как его использовать в контексте for
-loops?
Я читал эту ветку: Как перебрать строки файла?
Что такое IFS
? И как его использовать в контексте for
-loops?
Ответы:
IFS
обозначает - это символ, который разделяет поля. В примере, который вы разместили, он установлен на символ новой строки ( ); поэтому после его установки текст будет обрабатываться построчно. В этом примере вы можете изменить значение (на некоторую букву, которая есть во входном файле) и проверить, как будет разделяться текст.Input
Internal Field Separator
\n
for
IFS
Кстати, из ответа вы опубликовали второе решение, которое рекомендуется ...
Как @jasonwryan заметил, что это не Input
но Internal
. Название Input
пришло из awk
которого тоже есть OFS
- Output Field Separator
.
S
был для сепаратора в оболочке Bourne, откуда он произошел. В оболочке Korn и в большинстве других оболочек типа Bourne, как это было определено ранее POSIX
, параметр S
is for Delimiter (просто немного напрягает воображение), A::B:
например, разделен на «A», «» и «B» (без дополнительных ""). Это отличается от awk
's FS
или s
флага расширения параметра zsh
.
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
, rldh
(где 
это символ новой строки) и wdy
.
"IFS indirectly determines how ..."
?
IFS
(напрямую) определяет способ разбиения выходных данных подстановки команд, который затем (косвенно) определяет цикл.
Из man bash
IFS Внутренний разделитель полей, который используется для разделения слов после раскрытия и разделения строк на слова с помощью встроенной команды read. Значением по умолчанию является «<пробел> <вкладка> <новая строка>».
Это одна из внутренних переменных Bash. Он определяет, как Bash распознает поля или границы слов при интерпретации символьных строк.
Хотя по умолчанию используется пробел (пробел, табуляция и новая строка), его можно изменить, например, для анализа файла данных, разделенных запятыми.
В дополнение к предыдущим отличным ответам, позвольте мне добавить, что 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, чтобы избежать нежелательных поломок в других частях скрипта.