Как добавить новые строки при использовании эха

42

Почему следующая команда не вставляет новые строки в сгенерированный файл и каково решение?

$ echo "Line 1\r\nLine2" >> readme.txt

$ cat readme.txt 
Line 1\r\nLine2
Саид Йездани
источник
6
Является ли echoобязательным? Вы можете использовать printf.
Архемар
Я не знал о printf, с printf она работает: P ... так что же тогда делает не работать с echo?
Саид Яздани
Включено \rв вывод или является частью CRLFновой строки?
cuonglm
9
Существует множество различных реализаций echoкоманд, несовместимых друг с другом. При этом рекомендуется использовать более стандартный инструмент, как printf. См. Unix.stackexchange.com/questions/65803/… для расширенного обзора проблемы.
Джимми
В переполнении стека новая строка Echo в Bash печатает литерал \ n Новая строка Echo в Bash печатает литерал \ n имеет несколько полезных ответов.
Грэм Перрин

Ответы:

38

echo


echoРеализация которых строго соответствует спецификации Single Unix будет добавить новые строки , если вы:

echo 'line1\nline2'

Но это не надежное поведение. На самом деле , нет никакого стандартного поведения, от которого вы можете ожидать echo.

ОПЕРАНДЫ

string

Строка для записи в стандартный вывод. Если первый операнд равен -nили если любой из операндов содержит символ < \backslash> , результаты определяются реализацией .

В XSI-совместимых системах, если первый операнд -n, он должен рассматриваться как строка, а не как опция . Следующие последовательности символов должны быть распознаны в XSI-совместимых системах в рамках любого из аргументов:

\a- Напишите <оповещение> .

\b- Напишите <backspace> .

\c- Подавить <newline>, который в противном случае следует за последним аргументом в выводе. Все символы, следующие за \cаргументами, должны игнорироваться.

\f- Напишите <form-feed> .

\n- Напишите <новую строку> .

\r- Напишите <возврат каретки> .

\t- Напишите <вкладку> .

\v- Напишите <вертикальную вкладку> .

\\- Напишите символ обратной косой черты.

\0num- Запишите 8-битное значение, которое является восьмеричным нулем, одной, двумя или тремя цифрами num.

И поэтому на самом деле нет никакого общего способа узнать, как написать новую строку echo, за исключением того, что вы, как правило, можете полагаться только echoна это.

bashОболочка обычно вовсе не соответствует спецификации, а также обрабатывает -nи другие варианты, но даже это является неопределенным. Ты можешь сделать:

shopt -s xpg_echo
echo hey\\nthere

hey
there

И даже не это необходимо, если bashбыл собран с опцией времени сборки ...

--enable-xpg-echo-default

Сделайте так, чтобы echoвстроенные расширения по умолчанию экранировали символы обратной косой черты, не требуя -eопции. Это устанавливает значение по умолчанию для xpg_echoопции оболочки on, что делает Bash echoболее похожим на версию, указанную в спецификации Single Unix, версия 3. Описание встроенных escape-последовательностей см. В Bash Builtinsecho .


printf


С другой стороны, printfповедение по сравнению с этим довольно ручное.

ОБОСНОВАНИЕ

printfУтилита была добавлена , чтобы обеспечить функциональные возможности, которые исторически предоставленным echo. Тем не менее, из-за непримиримых различий в различных существующих версиях echo, эта версия имеет несколько специальных функций, оставляя их для этой новой printfутилиты, которая основана на одной в системе Ninth Edition.

Раздел РАСШИРЕННОГО ОПИСАНИЯ почти точно соответствует printf()функции в стандарте ISO C, хотя он описан в терминах нотации формата файла в нотации формата файла XBD .

Он обрабатывает строки формата, которые описывают его аргументы - это может быть любое количество вещей, но для строк это в значительной степени либо %bстроки yte, либо буквальные %strings. Кроме %fорматов в первом аргументе, он ведет себя как %bстроковый аргумент, за исключением того, что он не обрабатывает \cescape.

printf ^%b%s$ '\n' '\n' '\t' '\t'

^
\n$^    \t$

Видишь Почему printfлучше чем echo? для большего.


echo() printf


Вы можете написать свои собственные стандарты, echoкак ...

echo(){
    printf '%b ' "$@\n\c"
}

... который всегда должен делать правильные вещи автоматически.

На самом деле, нет ... Это печатает литерал \nв хвосте аргументов, если последний аргумент заканчивается нечетным числом <обратных слешей> .

Но это не так:

echo()
    case    ${IFS- } in
    (\ *)   printf  %b\\n "$*";;
    (*)     IFS=\ $IFS
            printf  %b\\n "$*"
            IFS=${IFS#?}
    esac
mikeserv
источник
+1 для shopt -s xpg_echoопции в echoиспользовать -eпо умолчанию.
Виньеш Раджа
Это решение не работает без -e. Я удивлен, что никто не заметил этого, кроме, возможно, @HaydeSchiff
ha9u63ar
@ ha9u63ar - эээ ... ты это читал?
mikeserv
27

Передайте флаг -e в echo, чтобы он анализировал экранированные символы, такие как «\ r \ n», например:

echo -e "Line 1\r\nLine2" >> readme.txt
Хайден Шифф
источник
Хорошая простая опция "-e", чтобы заставить работать escape-последовательности - это говорит о другом ответе, который echoненадежен и не соответствует стандартам в отличие printf.
Эдвард
1
Убедитесь, что ваш скрипт не содержит никаких буквальных символов \ r \ n, например, в tr -d "\n"команде.
Нумен
8

Во всех версиях bash, которые я использовал, вы можете просто вставить буквальную новую строку в строку либо в интерактивном режиме, либо в сценарии, при условии, что строка достаточно заключена в кавычки.

Интерактивное:

$ echo "Line one
> Line two"
Line one
Line two
$

В скрипте:

echo "Line one
Line two"
Цифровая травма
источник
4
echo -e "Line 1\r\nLine2" >> readme.txt

дальнейшие возможности использования:

man echo
zodo
источник
2

Люди уже ответили адекватно, но я отказываюсь принимать мир, в котором эхо принимает любой вариант, кроме -n.

nl='
'
echo Line 1"$nl"Line 2"$nl"Line 3
Staven
источник
1

Если у вас есть персонаж, который не является частью сообщения, вы можете передать через sed

$ echo "Time on the next line:@$(date +"%Y-%m-%dT%T%z")" | sed -e's/@/\n/g'
Time on the next line:
2016-03-25T10:12:39-0500
verisimilidude
источник