3

При использовании оболочки Linux я сталкиваюсь со следующей ситуацией:

$ A=B\
> C
$ echo $A
BC

На мой взгляд, когда новая строка встречается с escape-символом, она не может быть символом CR, но все равно будет новой строкой. echo $A следует интерпретировать как echo B newline C а новая строка должна быть IFS для echo . Таким образом, на выходе должно быть B C вместо BC .

Почему я получаю вывод, который я делаю?

3 ответа3

3

Цитата man bash , раздел Цитирование:

Обратная косая черта без кавычек (\) является escape-символом. Он сохраняет буквальное значение следующего символа, за исключением <newline> . Если появляется пара \<newline> и обратная косая черта сама по себе не заключена в кавычки, \<newline> рассматривается как продолжение строки (то есть она удаляется из входного потока и фактически игнорируется).

Это позволяет разбивать очень длинные команды / последовательности команд (конвейер и преобразование вывода и т.д.) В сценариях на несколько строк для удобства чтения.


Чтобы заставить его обрабатывать новую строку так, как вы ожидаете, просто оберните значение (и любое последующее использование переменной) в кавычки.

$ A="B
> C"
$ echo "$A"
B
C

Из того же раздела:

Заключение символов в одинарные кавычки сохраняет буквальное значение каждого символа в кавычках. ...

Заключение символов в двойные кавычки сохраняет буквальное значение всех символов в кавычках, за исключением $, `, \ и, когда расширение истории включено,!. Символы $ и `сохраняют свое особое значение в двойных кавычках. Обратная косая черта сохраняет свое особое значение только в том случае, если за ней следует один из следующих символов: $, `,", \ или.

1

Отвечая на вопрос "почему" на "почему это полезно":

Backslash-newline используется для продолжения строки, чтобы разбить очень длинные строки:

Обратная косая черта в конце строки в сценарии оболочки заставляет оболочку игнорировать символ новой строки для выполнения сценария. Обычно это используется для разделения длинных строк в файле сценария на несколько текстовых строк, которые будут обрабатываться оболочкой как одна строка сценария.

Например, команда

git log --tags --branches HEAD FETCH_HEAD ORIG_HEAD --graph --decorate --pretty=oneline --simplify-by-decoration

можно записать как

git log --tags --branches HEAD FETCH_HEAD ORIG_HEAD \
    --graph --decorate --pretty=oneline --simplify-by-decoration
0
A=B\
C

означает «A равно строке B, за которой следует игнорирование новой строки, за которой следует C»

В том, что вы напечатали, нет CR, если оболочка его видит. Конец строки в Linux/Unix - это перевод строки (LF), а не CR. CR испускается как часть обработки терминала. Большинству терминалов требуется перевод строки для удаления строки и возврат каретки для отправки курсора назад влево. CR вставляется ядром при отправке перевода строки на терминал, когда терминалу это необходимо - IOW, он не виден оболочке. Обратите внимание, что, например, визуальный редактор может разделять использование CR и LF - наименьшее количество символов для следующего перезаписываемого участка экрана вполне может включать LF (чтобы перейти вниз по странице без изменения столбца).

Немного более запутанно, есть также перевод ввода для клавиатур. Клавиша Enter обычно отправляет возврат каретки (Control-M). Но чтобы распознать введенную команду, оболочка должна увидеть конец строки. Поэтому дополнительный параметр stty описывает для обработки терминала ядра, что входной CR должен быть переведен в конец строки. Таким образом, оболочка все еще не видит CR.

Конечным результатом является то, что терминал отправляет:

A=B\<CR>C<CR>

Оболочка получает:

A=B\<LF>C<LF>

Оболочка анализирует это как "о, перевод строки с обратной косой черты - я просто игнорирую это" и в результате получается:

A=BC<LF>

И на выходе ядро изменяет последовательность, отправляемую терминалу во время ввода команды:

A=B\<CR><LF>C<CR><LF>

Ядро обработки терминалов управляется командой оболочки stty и, в зависимости от реализации (Linux, Mac OS X, * BSD), базовые детали должны находиться под man termios , man tty_ioctl . man console_ioctl и т. д.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .