エコーを使用するときに新しい行を追加する方法


42

次のコマンドが生成されたファイルに新しい行を挿入しないのはなぜですか?

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

$ cat readme.txt 
Line 1\r\nLine2

6
あるecho必須?を使用できますprintf
アルケマール

私はprintfについて知りませんでした、printfで動作します:P ...それでは、エコーで動作しないのは何ですか?
Saeidヤズダニ

ですが\r、出力に含めるかのそれの一部CRLF改行?
-cuonglm

9
echo互いに互換性のないコマンドのさまざまな実装があります。したがって、より標準的なツールを使用することをお勧めしますprintf。問題の詳細な概要については、unix.stackexchange.com / questions / 65803 /…を参照してください。
-jimmij

スタックオーバーフローでは、BashのEcho改行はリテラルを出力します\ nBashのEcho改行はリテラルを出力します\ nにはいくつかの有用な答えがあります。
グラハムペリン

回答:


38

echo


echoSingle Unix Specificationに厳密に準拠する実装では、次の場合に改行が追加されます。

echo 'line1\nline2'

しかし、それは信頼できる動作ではありません。実際、期待できる標準的な動作はありませんecho

オペランド

string

標準出力に書き込まれる文字列。最初のオペランドがの-n場合、またはいずれかのオペランドに< \バックスラッシュ>文字が含まれている場合、結果は実装定義です。

XSI準拠の最初のオペランドがある場合のシステム、-nそれは文字列として扱われるものではないオプション。次の文字シーケンスは、任意の引数内のXSI準拠システムで認識されます。

\a- <アラート>を記述します

\b- <backspace>を記述します

\c- 出力の最後の引数の後に続く<newline>を抑制します\c引数に続くすべての文字は無視されます。

\f- <form-feed>を記述します

\n- <newline>を記述します

\r- <carriage-return>を記述します。

\t- <tab>を記述します

\v- <vertical-tab>を記述します

\\- <バックスラッシュ>文字を記述します

\0num-ゼロ、1、2、または3桁の8進数である8ビット値を書き込みnumます。

したがってecho、を使用して改行を記述する方法を知る一般的な方法は実際にはありませんecho

bashシェルは通常んではない仕様に準拠し、ハンドル-nやその他のオプションを、それでも不確実であること。できるよ:

shopt -s xpg_echo
echo hey\\nthere

hey
there

そして、もないという場合には必要であるbashビルド時のオプションで構築されています...

--enable-xpg-echo-default

オプションechoを必要とせずに、ビルトインがデフォルトでバックスラッシュでエスケープされた文字を展開するようにし-eます。これにより、xpg_echoシェルオプションのデフォルト値がに設定され、onBash echoがSingle Unix Specificationバージョン3で指定されたバージョンのように動作するようになります。認識されるエスケープシーケンスの説明については、Bash Builtinsを参照してくださいecho


printf


一方、printfの動作は比較してかなり飼いならされています。

根拠

このprintfユーティリティは、以前から提供されていた機能を提供するために追加されましたecho。ただし、既存のさまざまなバージョンには互換性のない違いがあるためecho、このバージョンには特別な機能がほとんどなくprintf、第9版システムの1つに基づいたこの新しいユーティリティにそれらを残しています。

EXTENDED DESCRIPTIONセクションprintf()は、ISO C標準の機能とほぼ完全に一致しますが、XBD File Format Notationのファイル形式表記法で説明されています。

引数を記述するフォーマット文字列を処理します-これは任意の数になりますが、文字列の場合はほとんど%byte文字列かリテラル文字列%sです。%f最初の引数のオーマット以外は%b\cエスケープを処理しないことを除いて、yte文字列引数とほとんど同じように動作します。

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

^
\n$^    \t$

なぜprintfよりも優れているのをechoご覧ください多くのための。


echo() printf


次のechoような独自の標準準拠を作成することができます...

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

...これはほとんど常に正しいことを自動的に行うはずです。

実際、いいえ... \n最後の引数が奇数の<backslashes>で終わる場合、引数の末尾にリテラルを出力します

しかし、これはそうではありません:

echo()
    case    ${IFS- } in
    (\ *)   printf  %b\\n "$*";;
    (*)     IFS=\ $IFS
            printf  %b\\n "$*"
            IFS=${IFS#?}
    esac

デフォルトで使用するshopt -s xpg_echoオプションの+1 。echo-e
ヴィニェシュラジャ

このソリューションはなしでは機能しません-e。おそらく@HaydeSchiff
ha9u63ar

@ ha9u63ar-うーん...これを読みましたか?
mikeserv

27

-eフラグをechoに渡して、「\ r \ n」などのエスケープ文字を次のように解析します。

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

エスケープシーケンスを機能させる素敵なシンプルな「-e」オプション- echo信頼性が低く、標準とは異なる標準に従わない別の答えを示していますprintf
エドワード

1
スクリプトに、tr -d "\n"コマンドなどのリテラル\ r \ 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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.