'\ 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')

не буде працювати, оскільки заміна команди ( $(...)) знімає всі символи, що знаходяться в новому рядку. Однак ви можете використовувати:

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

Що працює, тому що висновок printfзакінчується "символом, а не новим рядком.

Тепер, для повноти, в rcоболонці та похідних (як-от esабо 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) використовувати цей метод евакуації, ви все одно можете використовувати:

IFS='
'

що рівнозначно, але важче читати.

BTW: Це розширення вже минуло стандартну комісію POSIX, але воно заплановане на SUSv8, який, як очікується, з'явиться не до 2020 року, тому що спочатку нам потрібно працювати над нашим відставанням від поточного списку помилок.


Ці $'...'розкладання відрізняється від echo. Вони більше схожі на аргументи формату printf. Тому echoщо 0, потрібний в режимі " \0123до" $'...'та " printfформатом", \0123буде \012
новим рядком з наступним літеральним номером

1
Зауважте, що $'...'специфікація все ще обговорюється. Є кілька питань, які ще мають бути вирішені з запропонованою на даний момент формулюванням.
Стефан Шазелас

IIRC, він був закритий, але був відновлений. Зважаючи на те, що перед її набуттям ще багато часу, я не бачу справжньої проблеми з цим.
schily

1
Він був закритий, я висунув кілька заперечень, він був знову відкритий, він був потім внесений поправки, є ще кілька проблем (більшість з них щодо \uxxxxрозширення), і немає жодної резолюції, яка б відповідала існуючим реалізаціям. Таким чином, він може не перейти в наступну версію POSIX. Можливо, вони можуть залишити \uxxxxрозширення для випуску8, тож ми все одно можемо мати принаймні $'\n'.
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.