Каково точное значение IFS = $'\n'?

Если следующий пример, который устанавливает переменную среды IFS символу строки...

IFS=$'\n'
  • Что означает знак доллар точно
  • Что он делает в этом конкретном случай?
  • Где я могу узнать больше об этом конкретном использовании (Google не разрешает специальные символы при поиске, и я не знаю, что искать в противном случае)?

Я знаю, что такое переменная среды IFS, и какой символ \n (строка), но почему бы просто не использовать следующую форму: IFS="\n" (который не работает)?

Например, если я хочу перебирать каждую строку файла и хочу использовать цикл for, я мог бы сделать это:

for line in (< /path/to/file); do
    echo "Line: $line"
done

Однако это не будет работать правильно, если только IFS не установлен на символ линии. Чтобы заставить его работать, я должен был бы сделать это:

OLDIFS=$IFS
IFS=$'\n'
for line in (< /path/to/file); do
    echo "Line: $line"
done
IFS=$OLDIFS

Примечание: Мне не нужен другой способ сделать то же самое, я знаю много других... Мне только интересно, что $'\n' и задавался вопросом, может ли кто-нибудь дать мне объяснение на нем.

Ответ 1

Обычно bash не интерпретирует escape-последовательности в строковых литералах. Поэтому, если вы пишете \n или "\n" или '\n', это не строка - это буква n (в первом случае) или обратная косая черта, сопровождаемая буквой n (в двух других случаях).

$'somestring' - синтаксис для строковых литералов с escape-последовательностями. Таким образом, в отличие от '\n', $'\n' на самом деле является строкой.

Ответ 2

Просто, чтобы дать конструктору его официальное название : строки формы $'...' называются ANSI C-quoted строки.

То есть, как в строках [ANSI] C, escape-последовательности обратного вызова распознаются и расширяются до их эквивалентного литерала (см. ниже полный список поддерживаемых управляющих последовательностей).

После этого расширения строки $'...' ведут себя так же, как '...' строки, т.е. они рассматриваются как литералы, не подлежащие никаким [дальнейшим] расширениям оболочки.

Например, $'\n' расширяется до символа символа новой строки, который является чем-то регулярным bash строковым литералом (без '...' или "..."). [1]

Еще одна интересная особенность заключается в том, что строки ANSI C могут выходить ' (одинарные кавычки) как \', что '...' (обычные строки с одной кавычкой) не может:

echo $'Honey, I\'m home' # OK; this cannot be done with '...'

Список поддерживаемых escape-последовательностей:

Управляющие последовательности обратного слэша, если они есть, декодируются следующим образом:

\ а alert (звонок)

\ б Забой

\ е \ E escape-символ (не ANSI C)

\ е form feed

\ п новая строка

\ г возврат каретки

\ т горизонтальная вкладка

\ v вертикальная вкладка

\ обратной косой черты

\ "одиночная кавычка

\" двойная кавычка

\nNN восьмибитовый символ, значением которого является восьмеричное значение nnn (от одной до трех цифр)

\ xHH восьмибитовый символ, значение которого представляет собой шестнадцатеричное значение HH (одна или две шестнадцатеричные цифры)

\ Uhhhh символ Unicode (ISO/IEC 10646), значение которого представляет собой шестнадцатеричное значение HHHH (от одной до четырех шестнадцатеричных цифр)

\ UHHHHHHHH символ Unicode (ISO/IEC 10646), значение которого представляет собой шестнадцатеричное значение HHHHHHHH (от одной до восьми шестнадцатеричных цифр)

\ сх символ control-x

Расширенный результат одинарный, как будто знак доллара не присутствовал.


[1] Вы можете, однако, внедрить фактические строки в строки "..." и "..."; т.е. вы можете определить строки, которые охватывают несколько строк.

Ответ 3

Из http://www.linuxtopia.org/online_books/bash_guide_for_beginners/sect_03_03.html:

Слова в форме "$ STRING" обработанный особым образом. Слово расширяется до строки, с заменены символы с обратной косой чертой как указано в стандарте ANSI-C. Последующие последовательности обратной косой черты могут быть найденный в Bash documentation.found

Я предполагаю, что он заставил script выйти из строки в соответствующий стандарт ANSI-C.

Ответ 4

Повторное восстановление IFS по умолчанию - это не требуется OLDIFS=$IFS. Запустите новый IFS в подоболочке, чтобы избежать переопределения IFS по умолчанию:

ar=(123 321); ( IFS=$'\n'; echo ${ar[*]} )

Кроме того, я действительно не верю, что вы полностью восстановите старый IFS. Вы должны удвоить его, чтобы избежать разрыва строки, например OLDIFS="$IFS".

Ответ 5

Строки с котировками ANSI - ключевой момент. Благодаря @mklement0.

Вы можете протестировать строки с котировкой ANSI с командой od.

echo -n $'\n' | od -c
echo -n '\n' | od -c
echo -n $"\n" | od -c
echo -n "\n" | od -c

Выходы:

0000000  \n  
0000001

0000000   \   n   
0000002

0000000   \   n   
0000002

0000000   \   n   
0000002

Вы можете четко понимать значение вывода.

Ответ 6

Это похоже на извлечение значения из переменной:

VAR='test'
echo VAR
echo $VAR

разные, поэтому знак доллара в основном оценивает содержимое.