Как я могу иметь новую строку в строке в sh?
этой
STR="HellonWorld"
echo $STR
производит как выход
HellonWorld
вместо
Hello
World
что я должен сделать, чтобы иметь новую строку в строке?
Примечание: этот вопрос не о Эхо.
Я в курсе echo -e
, но я ищу решение, которое позволяет передавать строку (которая включает новую строку) в качестве аргумента другое команды, которые не имеют аналогичной опции для интерпретации n
'S, как новая строка.
10 ответов:
решение заключается в использовании
$'string'
, например:$ STR=$'Hello\nWorld' $ echo "$STR" Hello World
вот выдержка из страницы руководства Bash:
Words of the form $'string' are treated specially. The word expands to string, with backslash-escaped characters replaced as specified by the ANSI C standard. Backslash escape sequences, if present, are decoded as follows: \a alert (bell) \b backspace \e \E an escape character \f form feed \n new line \r carriage return \t horizontal tab \v vertical tab \ backslash \' single quote \" double quote \nnn the eight-bit character whose value is the octal value nnn (one to three digits) \xHH the eight-bit character whose value is the hexadecimal value HH (one or two hex digits) \cx a control-x character The expanded result is single-quoted, as if the dollar sign had not been present. A double-quoted string preceded by a dollar sign ($"string") will cause the string to be translated according to the current locale. If the current locale is C or POSIX, the dollar sign is ignored. If the string is translated and replaced, the replacement is double-quoted.
Эхо настолько девяносто и так чревато опасностями, что его использование должно привести к дампам ядра не менее 4 ГБ. Серьезно, проблемы echo были причиной того, что процесс стандартизации Unix, наконец, изобрел
printf
утилита, избавляющая от всех проблем.Итак, чтобы получить новую строку в строке:
FOO="hello world" BAR=$(printf "hello\nworld\n") # Alternative; note: final newline is deleted printf '<%s>\n' "$FOO" printf '<%s>\n' "$BAR"
там! Нет SysV против BSD Echo madness, все аккуратно печатается и полностью переносится поддержка C escape-последовательностей. Все, пожалуйста, используйте
printf
теперь и никогда не оглядывайся назад.
то, что я сделал на основе других ответов было
NEWLINE=$'\n' my_var="__between eggs and bacon__" echo "spam${NEWLINE}eggs${my_var}bacon${NEWLINE}knight" # which outputs: spam eggs__between eggs and bacon__bacon knight
проблема не в оболочке. Проблема на самом деле с
echo
сама команда, и отсутствие двойных кавычек вокруг переменной интерполяции. Вы можете попробовать использоватьecho -e
но это не поддерживается на всех платформах, и одна из причинprintf
теперь рекомендуется для переносимости.вы также можете попробовать вставить новую строку непосредственно в сценарий оболочки (если сценарий-это то, что вы пишете), так что это выглядит...
#!/bin/sh echo "Hello World" #EOF
или эквивалентно
#!/bin/sh string="Hello World" echo "$string" # note double quotes!
единственная простая альтернатива-фактически ввести новую строку в переменную:
$ STR='new line' $ printf '%s' "$STR" new line
Да, это значит писать введите где это необходимо в коде.
есть несколько эквивалентов
new line
символ.\n ### A common way to represent a new line character. 2 ### Octal value of a new line character. \x0A ### Hexadecimal value of a new line character.
но все это требует "интерпретации" каким-то инструментом ( POSIX printf):
echo -e "new\nline" ### on POSIX echo, `-e` is not required. printf 'new\nline' ### Understood by POSIX printf. printf 'new2line' ### Valid in POSIX printf. printf 'new\x0Aline' printf '%b' 'new12line' ### Valid in POSIX printf.
и поэтому инструмент требуется для сборки строка с новой строкой:
$ STR="$(printf 'new\nline')" $ printf '%s' "$STR" new line
в некоторых оболочках последовательность $' специальное расширение раковины. Известно, что работает в ksh93, bash и zsh:
$ STR=$'new\nline'
конечно, возможны и более сложные решения:
$ echo '6e65770a6c696e650a' | xxd -p -r new line
или
$ echo "new line" | sed 's/ \+/\n/g' new line
найти
-e
флаг элегантный и прямой вперед
STR="Hello\nWorld" echo -e $STR
выходы#Hello World
если строка является результатом другой команды, я просто использую кавычки
indexes_diff=$(git diff index.yaml) echo "$indexes_diff"
Я не эксперт bash, но этот работал для меня:
STR1="Hello" STR2="World" NEWSTR=$(cat << EOF $STR1 $STR2 EOF ) echo "$NEWSTR"
Я нашел это проще для форматирования текстов.
a $ прямо перед одинарными кавычками '...\северный... как следует, однако двойные кавычки не работает.
$ echo $'Hello\nWorld' Hello World $ echo $"Hello\nWorld" Hello\nWorld
в моей системе (Ubuntu 17.10) ваш пример просто работает по желанию, как при вводе из командной строки (в
sh
) и при выполнении какsh
сценарий:[bash]§ sh $ STR="Hello\nWorld" $ echo $STR Hello World $ exit [bash]§ echo "STR=\"Hello\nWorld\" > echo $STR" > test-str.sh [bash]§ cat test-str.sh STR="Hello\nWorld" echo $STR [bash]§ sh test-str.sh Hello World
Я думаю, это ответ на ваш вопрос: он просто работает. (Я не пытался выяснить детали, такие как в какой момент именно замена символа новой строки для
\n
происходитsh
).однако я заметил, что этот же скрипт будет вести себя по-разному при выполнении С
bash
и печатьHello\nWorld
вместо:[bash]§ bash test-str.sh Hello\nWorld
мне удалось получить желаемый результат с
bash
следующим образом:[bash]§ STR="Hello > World" [bash]§ echo "$STR"
обратите внимание на двойные кавычки
$STR
. Это ведет себя одинаково, если сохранить и запустить какbash
сценарий.следующее также дает желаемый результат:
[bash]§ echo "Hello > World"
те придирчивые, которые нуждаются только в новой строке и презирают многострочный код, который нарушает отступ, может сделать:
IFS="$(printf '\nx')" IFS="${IFS%x}"
Bash (и, вероятно, другие оболочки) сожрать все конечные новые строки после замены команды, так что вам нужно закончить
printf
строка с символом перевода строки и удалить его после этого. Это также может легко стать проявляющаяся.IFS="$(printf '\nx')" IFS="${IFS%x}"
Я знаю, что это два действия вместо одного, но мой отступ и переносимость ОКР at peace now :) Я изначально разработал это, чтобы иметь возможность разделить вывод только новой строки, и я в конечном итоге использовал модификацию, которая использует
\r
как завершающий символ. Это делает работу разделения новой строки даже для вывода dos, заканчивающегося на\r\n
.IFS="$(printf '\n\r')"