В начале сценария оболочки bash находится следующая строка:
IFS=$'\n'
В чем смысл этой коллекции символов?
IFS=$'\n'является bashism (+ другие оболочки, использовать ANSI-C Цитирование , для обхода см stackoverflow.com/questions/10748703/...
В начале сценария оболочки bash находится следующая строка:
IFS=$'\n'
В чем смысл этой коллекции символов?
IFS=$'\n'является bashism (+ другие оболочки, использовать ANSI-C Цитирование , для обхода см stackoverflow.com/questions/10748703/...
Ответы:
IFSрасшифровывается как «внутренний разделитель полей». Он используется оболочкой для определения того, как выполнять разбиение слов, то есть как распознавать границы слов.
Попробуйте это в оболочке, такой как bash (другие оболочки могут обрабатывать это по-разному, например, zsh):
mystring="foo:bar baz rab"
for word in $mystring; do
echo "Word: $word"
done
Значение по умолчанию для IFSсостоит из пробельных символов (если быть точным: пробел, табуляция и новая строка). Каждый символ может быть границей слова. Таким образом, со значением по умолчанию IFS, цикл выше напечатает:
Word: foo:bar
Word: baz
Word: rab
Другими словами, оболочка считает, что пробел является границей слова.
Теперь попробуйте установить IFS=:перед выполнением цикла. На этот раз результат:
Word: foo
Word: bar baz rab
Теперь оболочка также разбивается mystringна слова - но теперь она рассматривает только двоеточие как границу слова.
Первый символ IFS- специальный: он используется для разделения слов в выводе при использовании специальной $*переменной (пример взят из Руководства по расширенному написанию сценариев Bash , где вы также можете найти дополнительную информацию о специальных переменных, подобных этой):
$ bash -c 'set w x y z; IFS=":-;"; echo "$*"'
w:x:y:z
По сравнению с:
$ bash -c 'set w x y z; IFS="-:;"; echo "$*"'
w-x-y-z
Обратите внимание , что в обоих примерах, оболочка будет по- прежнему относиться все символы :, -а ;также границы слов. Единственное, что меняется, это поведение $*.
Еще одна важная вещь, которую нужно знать, это то, как обрабатываются так называемые «пробелы IFS» . По сути, как только IFSвключаются пробельные символы, начальные и конечные пробельные символы удаляются из строки, которая должна быть разделена перед обработкой, а также последовательность последовательных пробельных символов также разделяет поля. Однако это относится только к тем пробельным символам, которые фактически присутствуют в IFS.
Например, давайте посмотрим на строку "a:b:: c d "(завершающий пробел и два пробела между символами cи d).
IFS=:он будет разделен на четыре поля: "a", "b", ""(пустая строка) и " c d "(опять же , два пространства между cи d). Обратите внимание на начальные и конечные пробелы в последнем поле.IFS=' :', она будет разделена на пять полей: "a", "b", ""(пустая строка), "c"и "d". Нет ни одного начального и конечного пробела.Обратите внимание, что во втором примере несколько последовательных пробельных символов разделяют два поля, а несколько последовательных двоеточий - нет (поскольку они не являются пробельными символами).
Что же касается IFS=$'\n', то есть ksh93синтаксис также поддерживается bash, zsh, mkshи FreeBSD sh(с вариациями между всеми оболочками). Цитирую man-страницу bash:
Слова вида $ 'string' обрабатываются специально. Слово расширяется до «строки», символы с обратной косой чертой заменяются в соответствии со стандартом ANSI C.
\nявляется escape-последовательностью для новой строки, поэтому в IFSконечном итоге устанавливается один символ новой строки.
bashруководство по написанию сценариев или что-то еще. В основном, информация, доступная по таким ссылкам, не хватает важными способами. Во всяком случае, таким образом, упускается два важных момента, касающихся расщепления оболочки - глобализация и пропуски IFS.
unset IFSоболочка ведет себя совсем иначе, чем IFS=. Кроме того, первый байт в IFS также особенный, "${named_array[*]}"но не имеет значения, когда расширение не
$IFS- одна из двух основных вещей, выполняемых при раскрытии переменной без кавычек в контексте списка (это splitчасть split+globоператора). Другой болтается. При использовании разделения работы, как правило, необходимо set -fотключить эту globчасть.
$IFSтакже используется readвстроенной командой
Внутри долларовых одинарных кавычек некоторые символы оцениваются специально. Например, \nпереводится на новую строку.
Таким образом, эта конкретная строка присваивает новую строку переменной IFS. IFS, в свою очередь, является специальной переменной в bash: Разделитель внутренних полей. Как man bashговорится, это
используется для разделения слов после раскрытия и разделения строк на слова с помощью
readвстроенной команды. Значением по умолчанию является<space><tab><newline>.
dollared single quotesкоторое отличается от простых одинарных кавычек.
Для краткости, IFS=$'\n'присвойте новую строку \nпеременной IFS.
$'string'Конструкция - это механизм цитирования, который используется для декодирования ANSI C, как escape-последовательности. Этот синтаксис исходит от ksh93, и был портативным современной оболочке , как bash, zsh, pdksh, busybox sh.
Этот синтаксис не определен POSIX, но был принят для выпуска SUS 7 .
Я предпочел объяснить $IFSна примере:
если вы хотите, чтобы cp, mv или другой файл обрабатывались, IFS пуст по умолчанию, когда ваши файлы имеют метасимвол или пробел, например:
Linux Administration.pdfили Free Software Fundation.ogg, конечно, у вас будет проблема, потому что: Linux рассматривает отдельный параметр и Администрация рассматривают отдельный параметр. Итак, bash имеет built-in variable, затем вы можете инициализировать IFS==$(echo -en "\n\b"), затем bash отбрасывает любой метасимвол и пробел между именем файла, например:
#!/bin/bash
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
mymusicdir=~/test/dd
find $mymusicdir -name "*" -execdir rename 's/ /_/g' "{}" +
IFS=$SAVEIFS