次のコードは、状況を最もよく表しています。最後の行が末尾の改行文字を出力しないのはなぜですか?各行の出力はコメントに示されています。私は使用していますGNU bash、バージョン4.1.5
echo -n $'a\nb\n' | xxd -p # 610a620a
x=$'a\nb\n' ; echo -n "$x" | xxd -p # 610a620a
echo -ne "a\nb\n" | xxd -p # 610a620a
x="$(echo -ne "a\nb\n")" ; echo -n "$x" | xxd -p # 610a62
コマンド置換関数$()
(およびその従兄弟のバッククォート)は、特に末尾の改行を削除します。これは 文書化された動作 であり、構成を使用するときは常に注意する必要があります。
テキスト本文内の改行は置換演算子によって削除されませんが、シェルで単語分割を行うときにも削除される可能性があるため、引用符を使用したかどうかによって結果が異なります。これら2つの使用法の違いに注意してください。
$ echo -n "$(echo -n 'a\nb')"
a
b
$ !! | xxd -p
610a62
$ echo -n $(echo -n 'a\nb')
a b
$ !! | xxd -p
612062
2番目の例では、出力は引用符で囲まれず、改行はWord分割として解釈され、出力にスペースとして表示されます。
コマンド置換を使用する場合、シェルはサブシェルでコマンドを実行し、それらのstdoutを返します。このプロセスでは、表彰がプレーンな分割単語を返すため、IFS文字はその重要性を失います(引用符で囲まれていない場合)。そのため、末尾の文字は削除されます。例えば:
_$ echo "$(echo -e '\n')" | wc
1 0 1
$ echo -e '\n' | wc
2 0 2
_
より実際的には、ディレクトリ名の間に改行があってもpwd
は機能しますが、$(pwd)
は機能しません。
通常の回避策は、コマンドの最後に何かを追加し、その後それを削除することです。