Як додати нові рядки при використанні echo


42

Чому наступна команда не вставляє нові рядки в створений файл і що таке рішення?

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

$ cat readme.txt 
Line 1\r\nLine2

6
Є чи echoобов'язковим? ви можете використовувати printf.
Архемар

Я не знав про printf, з printf він працює: P ... так що це робить, якщо тоді не працює з ехо?
Саїд Яздані

Чи \rвключається у вихід чи це частина CRLFнового рядка?
cuonglm

9
Існує безліч різних реалізацій echoкоманди, несумісних один з одним. Таким чином, рекомендується використовувати більш стандартний інструмент як printf. Див. Unix.stackexchange.com/questions/65803/… для розширеного огляду проблеми.
jimmij

Відповіді:


38

echo


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

echo 'line1\nline2'

Але це не є надійною поведінкою. Насправді, насправді немає жодної стандартної поведінки, якої можна очікувати echo.

ОПЕРАНДИ

string

Рядок, який слід записати на стандартний вихід. Якщо перший операнд є -n, або якщо будь-який з операндів містить символ < \зворотний косий рядок> , результати визначаються реалізацією .

У системах, сумісних з XSI , якщо перший операнд є -n, він повинен розглядатися як рядок, а не як варіант . Наступні послідовності символів повинні бути розпізнані в системах, що відповідають XSI, в межах будь-якого з аргументів:

\a- Напишіть <alert> .

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

\c- Пригнічіть <newline>, що в іншому випадку слідує за заключним аргументом у висновку. Усі символи, наведені \cв аргументах, ігноруються.

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

\n- Напишіть <newline> .

\r- Напишіть <carriage-return> .

\t- Напишіть <tab> .

\v- Напишіть <vertical-tab> .

\\- Введіть символ <зворотний проріз> .

\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. Дивіться Bash Builtins , щоб отримати опис послідовностей епізоду , що echoрозпізнається.


printf


З іншого боку, printfповедінка досить приборкано порівняно.

RATIONALE

printfУтиліта була додана , щоб забезпечити функціональні можливості, які історично наданим echo. Однак через непримиренні відмінності в різних версіях echoіснуючих версій є мало особливих особливостей, що залишає їх новій printfутиліті, яка базується на одній у системі Дев'ятого видання.

Розділ ДОСЛІДЖЕНОГО ОПИСУ майже точно відповідає printf()функції в стандарті ISO C, хоча він описаний термінами позначення формату файлу у форматі XBD File Notation .

Він обробляє рядки формату, які описують його аргументи - що може бути будь-якою кількістю речей, але для рядків - це майже будь- %bякі рядки yte або буквальні %sтренги. Окрім %fорматів у першому аргументі, він поводиться найбільше як %bаргумент yte string, за винятком того, що він не обробляє вхід \c.

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

+1 - shopt -s xpg_echoопція, яку echoможна використовувати -eза замовчуванням.
Vignesh Raja

Це рішення не працює без цього -e. Я здивований, що ніхто не помітив цього, окрім, можливо, @HaydeSchiff
ha9u63ar

@ ha9u63ar - uhh ... ти це читав?
mikeserv

27

Передайте прапор -e для відлуння, щоб він розібрав символи, що увійшли, наприклад "\ r \ n", наприклад:

echo -e "Line 1\r\nLine2" >> readme.txt

Хороший простий варіант "-e", щоб змусити працювати послідовності втечі - він говорить про іншу відповідь, яка не 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

2

Люди вже відповіли адекватно, але я відмовляюся приймати світ, де відлуння приймає будь-який варіант, окрім іншого -n.

nl='
'
echo Line 1"$nl"Line 2"$nl"Line 3

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.