Ответ 1
Почему символы новой строки, казалось, исчезли из переменной
Символы новой строки фактически сохраняются в переменной. Они не отображаются, потому что переменная в выражении echo
не заключена в двойные кавычки. Из кода:
echo $x
При использовании переменной без двойных кавычек выполняется разбиение слов. По умолчанию $IFS
(вики-запись в IFS), это означает, что все коллекции пробелов, включая новые строки и вкладки, заменяются на одно пространство.
Чтобы этого избежать, просто используйте двойные кавычки, как в:
echo "$x"
С этим единственным изменением вывод вашего script становится:
$ bash a,sh
---Pre function
hello
world
Hello
worldhello
world
hello
world
---In function
hello
world
Hello
worldhello
world
hello
world
---Post function
hello
world
Hello
worldhello
world
hello
world
Теперь отображаются строки новой строки, которые всегда были в переменной x
.
Кроме того: два слова, которые остаются натянутыми вместе
Обратите внимание, что комбинация worldhello
отображается в одной строке, потому что это то, о чем просил код:
printf "Hello\nworld"
echo $'hello\nworld'
printf
не печатает новую строку после world
. Следовательно, world
появляется в той же строке, что и следующая hello
.
Документация сведений
man bash
объясняет, что двойные кавычки блокируют расщепление слов:
Если подстановка появляется в двойных кавычках, разбиение слов и расширение пути не выполняются по результатам.
Разделение слов происходит после расширения переменной, команды подстановка и арифметическое расширение:
Оболочка сканирует результаты разложения параметров, команду замещения и арифметического расширения, которые не возникали внутри двойные кавычки для разбиения слов.
Еще одна тонкость заключается в том, что разбиение слова выполняется только в том случае, если имела место замещение:
Обратите внимание, что если разложение не происходит, расщепление не выполняется.
Обычно, когда выполняется разбиение слов, все строки пробелов, вкладок и строк новой строки заменяются одним пробелом. Это поведение по умолчанию можно изменить, изменив значение переменной IFS
:
Оболочка рассматривает каждый символ IFS как разделитель и разбивает результаты других расширений на слова по этим символам. Если IFS не установлен, или его значение в точности соответствует по умолчанию, затем последовательности пространства, табуляции и новой строки на начало и конец результатов предыдущих расширений игнорируется, и любая последовательность символов IFS не в начале или конец служит для разграничения слов. Если IFS имеет значение, отличное от по умолчанию, затем пробелы пробелов и вкладки игнорируются в начале и в конце слова, пока символ пробела находится в значении IFS (пробел IFS персонаж). Любой символ в IFS, который не является пробелом IFS, вдоль с любыми смежными символами пробела IFS, ограничивает поле. последовательность символов пробелов IFS также рассматривается как разделитель. Если значение IFS равно нулю, словосочетание не происходит.
Отладка
-
Используйте
set -x
Поместите строку
set -x
в начало кода, который вы хотите запустить. Результаты оценки каждой строки будут отображаться по мере запуска функции, каждая из которых предшествуетPS4
(по умолчанию это+
, пробел), чтобы отличить ее от обычного вывода.Отладочный вывод можно отключить, включив в него строку
set +x
.set -x
иset +x
оба работают также в командной строке. -
Используйте
stderr
Отправлять вывод отладки в
stderr
(дескриптор файла 2) следующим образом:echo "My Debug Info" >&2
По умолчанию конвейеры и подстановки команд работают только на
stderr
. Следовательно, информация, отправленная наstderr
, по умолчанию будет отображаться на терминале.
Подробнее о echo
По умолчанию echo
игнорирует escape-символы, а последовательность \n
просто означает a \
, за которой следует n
:
$ echo "Hello\nworld 4"
Hello\nworld 4
Чтобы \n
интерпретировался как новая строка, используйте -e
:
$ echo -e "Hello\nworld 4"
Hello
world 4