'\ n' в `IFS = $ '\ n' является переменной?

12

Я замечаю, что устанавливать новую строку IFSследует с префиксом $

IFS=$'\n'

но если установить двоеточие, просто

IFS=:

Является \nли переменная?

Исчисление
источник

Ответы:

21

Это $'...'в bashне параметр расширения, это особый вид цитаты введен ksh93, расширяющие те \n, \x0a, \12кода к символу новой строки. zshтакже добавил \u000a. ksh93а bashтакже есть, \cjпока zshимеет \C-J. ksh93также поддерживает такие варианты, как \x{a}.

Это $сигнал, что это какая-то форма или расширение. Но в любом случае он отличается от других форм расширений, которые используют $(например $((1 + 1)), $paramили $(cmd)), в том, что он не выполняется внутри двойных кавычек или здесь документов ( echo "$'x'"выводится $'x'во всех оболочках, хотя не определено для POSIX), и его расширение не подлежит разделению + glob, он определенно ближе к оператору цитирования, чем к оператору раскрытия.

IFS=\nустановит IFS n( \обрабатывается как оператор цитирования) и IFS="\n"или IFS='\n'установит IFS для двух символов обратной косой черты и n.

Вы также можете использовать:

IFS='
'

или

IFS="
"

или

IFS=$'
'

Чтобы передать буквальный символ новой строки, хотя это менее разборчивым (и никто не может видеть , чем использовать такие вещи , как set listв viтом , $IFSсодержит другие символы распорных в этом коде).

IFS=:, IFS=':', IFS=":", IFS=$':'Весь установленный МФС к :так что это не имеет значения , которые вы используете.

$'...'поддерживается (с вариациями) , по меньшей мере: ksh93, zsh, bash, mksh, BusyBox sh, FreeBSD sh. ksh93и bashтакже имеют $"..."форму кавычек, используемых для локализации текста, хотя это редко используется, поскольку это громоздко для развертывания и использования портативно и надежно.

В esи fishоболочки могут также использовать \nвне кавычек , чтобы развернуть на новую строку.

Некоторые инструменты, такие как printf, некоторые реализации echoили awkмогут также расширять их \nсами. Например, можно сделать:

printf '\n'
awk 'BEGIN{printf "\n"}'
echo
echo '\n\c' # UNIX compliant echos only

для вывода символа новой строки, но обратите внимание, что:

IFS = $ (printf '\ n')

не будет работать, потому что команда substitution ( $(...)) удаляет все завершающие символы новой строки. Однако вы можете использовать:

eval "$(printf 'IFS="\n"')"

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

Теперь, для полноты, в rcоболочке и производных (например, esor akanga), $'\n'действительно расширение этой \nпеременной (переменная, имя которой представляет собой последовательность из двух символов \и n). Эти оболочки не имеют ограничения на то , что символы имена переменных могут содержать и только один тип кавычек: '...'.

$ rc
; '\n' = (foo bar)
; echo $'\n'
foo bar
; echo $'\n'(1)
foo

rcВсе переменные также экспортируются в среду, но, по крайней мере, в варианте Unix rcдля имен переменных, таких как \nверсия переменной среды, имеет вид кодировки:

; env | grep foo | sed -n l
__5cn=foo\001bar$

( 0x5cбудучи байтовым значением ASCII \; см. также, как эта переменная массива была закодирована с байтом 0x1 в качестве разделителя).

Стефан Шазелас
источник
1
+1за обычный нечеловеческий уровень знаний
Стивен Пенни
10

Это ANSI-C цитирование :

Слова формы $'string'обрабатываются специально. Слово расширяется до stringсимволов с обратной косой чертой, заменяемых в соответствии со стандартом ANSI C.

Таким образом $'\n'заменяется символом новой строки.

Это не связано с расширением параметров оболочки , несмотря на использование $.

Стивен Китт
источник
6

Такие строки, как $'\n'были введены ksh93и в настоящее время не являются частью стандарта POSIX.

Они позволяют использовать большинство C-подобных выходов, например, $'\u2345'и выходы, которые также поддерживаются echo.

Обратите внимание, что если вы не любите (в случае ksh93 или bash) использовать этот метод escape, вы все равно можете использовать:

IFS='
'

что эквивалентно, но труднее читать.

Кстати: это расширение уже прошло стандартный комитет POSIX, но оно запланировано на SUSv8, который, как ожидается, появится не ранее 2020 года, потому что сначала нам нужно работать над нашим отставанием от текущего списка ошибок.

Шили
источник
Эти $'...'разложения отличается от echo. Они больше похожи на аргументы формата printf. Для echo, 0 требуется в \0123то время как для $'...'и printfформат, \0123будет \012новая строка, за которой следует буква 3.
Стефан Шазелас
1
Обратите внимание, что $'...'спецификация все еще обсуждается. Есть несколько вопросов, которые еще предстоит решить с помощью предлагаемой в настоящее время формулировки.
Стефан Шазелас
IIRC, он был закрыт, но был вновь открыт. В связи с тем, что до вступления в силу еще много времени, я не вижу в этом реальной проблемы.
Щили
1
Он был закрыт, я высказал несколько возражений, он был вновь открыт, затем в него были внесены поправки, все еще есть несколько проблем (большинство из них касаются \uxxxxрасширения), и не видно никакого решения, которое бы соответствовало существующим реализациям. Так что он может не попасть в следующую версию POSIX. Может быть, они могли бы оставить \uxxxxрасширение для выпуска 8, так что мы все еще можем иметь по крайней мере $'\n'.
Стефан Шазелас