5

これら2つのコマンドの出力が異なる理由を誰かが説明できますか?

$ echo "NewLine1\nNewLine2\n"
NewLine1
NewLine2
                         <-- Note 2nd newline here
$ echo "$(echo "NewLine1\nNewLine2\n")"
NewLine1
NewLine2
$                        <-- No second newline

"$( .... )" の出力の最後に新しい行を保持できる良い方法はありますか? ダミーの文字を追加して削除することも考えましたが、これらの新しい行がなくなる理由を知りたいです。

4

3 に答える 3

3

それが POSIX で指定されていることであり、Bourne シェルでは常にそのようになっているためです。

2.6.3 コマンド置換

コマンド置換を使用すると、コマンド名自体の代わりにコマンドの出力を置換できます。コマンドが次のように囲まれている場合、コマンド置換が発生します。

$(コマンド)

または(逆引用バージョン):

コマンド

シェルは、サブシェル環境 (シェル実行環境を参照) でコマンドを実行し、コマンド置換 (コマンドのテキストとそれを囲む "$()" または逆引用符) をコマンドの標準出力に置き換えることにより、コマンド置換を展開し、置換の最後にある 1 つ以上の <newline> 文字のシーケンス。出力の終わりの前に埋め込まれた <newline> 文字は削除されません。ただし、IFS の値と有効な引用符によっては、フィールド区切り文字として扱われ、フィールド分割中に削除される場合があります。出力に null バイトが含まれている場合、動作は規定されていません。

最後の改行を保持する 1 つの方法は次のようになります。

VAR="$(command; echo x)"   # Append x to keep newline(s).
VAR=${VAR%x}               # Chop x.

表示:

$ x="$(whoami; echo x)" ; printf '<%s>\n' "$x" "${x%x}"
<user
x>
<user
>

しかし、なぜ末尾の改行を削除するのでしょうか? 多くの場合、そのようにしたいからです。私もperlでプログラミングしていますが、行または変数を読み取ってから改行を切り刻む必要がある回数を数えることはできません:

while (defined ($string = <>)) {
    chop $string;
    frobnitz($string);
} 
于 2013-06-07T21:38:46.450 に答える
1

コマンド置換は、すべての末尾の改行を削除します。

1つを削除することは理にかなっています。例えば:

basename foo/bar

出力しますbar\n。の:

var=$(basename foo/bar)

ではなく、$varを含めたい。barbar\n

しかし、

var=$(basename $'foo/bar\n')

含めたいと思い$varますbar\n(結局のところ、改行はUnixのファイル名と同じくらい有効な文字です)。ただし、すべてのシェルは末尾の改行文字をすべて削除します。その欠陥は元の Bourne シェルにありrc、Bourne の欠陥のほとんどを修正したものでさえ、その欠陥は修正されていません。(ただし、改行文字を削除しない構文があります)rc``(){cmd}

POSIX シェルでは、この問題を回避するには、次のようにします。

var=$(basename -- "$file"; echo .)
var=${var%??}

その後、の終了ステータスを失っていますがbasename。あなたが修正できるもの:

var=$(basename -- "$file" && echo .) && var=${var%??}

${var%??}最後の 2 文字を削除することです。1 つ.目は上で追加したもので、2 つ目はによって追加された1 つのbasename改行文字です。他の改行文字がある場合はファイル名の一部になるため、コマンド置換でこれ以上削除することはありません。のベースを取得するので、それらが必要です。

オペレーターを持たない Bourne シェルでは${var%x}、それを回避するために長く複雑な方法を取らなければなりませんでした。

于 2013-06-07T21:32:15.277 に答える
1

改行が削除されていない場合は、次のような構造になります。

x="$(pwd)/filename"

役に立たないだろうが、Unix を書いた人々は有用な振る舞いを好んだ。

簡単に言えば、非常に昔 (1983 年、おそらく 1984 年など) に、私は Unix の特定のバリアントで、末尾の改行を削除しないシェルの更新に悩まされました。それはいたるところでスクリプトを壊しました。それは非常に迅速に修正されました。

于 2013-06-07T23:09:31.840 に答える