echo "bar" -nがecho -n "bar"と異なるのはなぜですか?


10

比較する

echo -n "bar"

echo "bar" -n

前者は私が思っていることを実行します(改行なしで「bar」を出力します)が、後者はそうではありません。これはバグですか、それとも仕様ですか?オプションを移動できないという点で、多くのCLIプログラムとは異なるのはなぜですか?たとえば、tail -f /var/log/messagesはとまったく同じtail /var/log/messages -fです。前者が欲しかったのを忘れたときに、後者を実行することがあります。これは、通常、オプションと引数が通常getoptによって再配置されるためです。

更新:はい、私は最初に質問を神経質にしました。答えを理解するために履歴を表示する必要がある神経を削除しました。


3
私が見たところ、違いすぐにわかります。echo -n "bar"「bar」をecho "bar" -n与える一方、「bar -n」を与える
phunehehe

回答:


18

他のほとんどの人が観察したように、「-n」は、echoコマンドの直後以外のどこかに置かれた場合、文字どおりに解釈されます。

歴史的に、UNIXユーティリティはすべてこのようなものでした-コマンド名の直後にのみオプションを探していました。今でもPOSIXは古い方法を正しいと指定しているため(ガイドライン9およびman 3 getoptLinuxシステムでも)、より柔軟なスタイルを開発したのはおそらくBSDまたはGNUでした。とにかく、最近のほとんどのLinuxユーティリティは新しいスタイルを使用していますが、などのいくつかのホールドアウトがありechoます。

EchoPOSIXが登場するまでに、少なくとも2つの根本的に矛盾するバージョンが機能していたという点で、標準的には混乱しています。一方では、バックスラッシュでエスケープされた文字を解釈するSYSVスタイルがありますが、それ以外の場合は引数を文字どおりに扱い、オプションを受け入れません。一方、BSDスタイルがあります。これは、イニシャル-nを特殊なケースとして扱い、その他すべてを文字どおり完全に出力します。また、echoは非常に便利なので、いずれかの動作に依存する何千ものシェルスクリプトがあります。

echo Usage: my_awesome_script '[-a]' '[-b]' '[-c]' '[-n]'
echo -a does a thing.
echo -b does something else.
echo -c makes sure -a works right.
echo -- DON\'T USE -n -- it\'s not finished! --

「すべてを文字通り処理する」セマンティックのため、echo物事を壊さずに新しいオプションを追加することさえ不可能です。GNUがそれに柔軟なオプションスキームを使用した場合、地獄は壊れるでしょう。

ちなみに、Bourneシェルの実装間の最適な互換性のために、ではprintfなくを使用してくださいecho

echo特に柔軟なオプションを使用しない理由を説明するために更新されました。


あなただけが期待されるgetoptの振る舞いであることを言及しているので、賛成票を投じてください。
Geoffrey Bachelet

@janderエコーが「ホールドアウト」になるのはなぜですか?私はそれがgnu coreutilだと思いますか?
xenoterracide 2011年

@xeno:回答を更新しました。基本的に、GNUは物事を壊したくありませんでした。
Jander

1
最初の非オプションの後にオプションを受け入れることは、GNUユーティリティおよびGNU libcgetopt機能を使用するプログラムに固有です。ユーザーは、環境変数を設定することにより、常に下位互換性のある動作を得ることができますPOSIXLY_CORRECT
Gilles「SO-邪悪なことをやめよう」

1
の特定のケースについてはecho、オプションとして認識-eまたは実装する実装も-Eあります。移植性のために、で始めたり、-などを使用したりしないでくださいprintf %s -e
Gilles「SO-邪悪なことをやめなさい」

9

他の回答では、manページを見て、-nがエコーする文字列の一部になっていることがわかります。ただし、md5sumを使用せずにこれを調査するのは簡単で、何が起こっているのかが少しわかりにくくなっていることを指摘したいだけです。

[11:07:44][dasonk@Chloe:~]: echo -n "bar"
bar[11:07:48][dasonk@Chloe:~]: echo "bar" -n
bar -n

3
正確に+1。パイプラインが期待どおりに動作しない場合は、各部分を個別にテストします。
Mikel

6

うわー、みんなの説明は長いです。

これは簡単です:

-n 文字列の前に表示される場合はオプションで、それ以外の場合はエコーされる別の文字列です。

を削除する| md5sum と、出力が異なることがわかります。


5

簡単な検査から、これは設計上のバグではありません...

echo "bar" -n | md5sum

a3f8efa5dd10e90aee0963052e3650a1

このコマンドを自分で試してください:

echo "bar -n" | md5sum

結果のmd5が

a3f8efa5dd10e90aee0963052e3650a1

エコーでの-nの使用を混同しただけです。

最初のサンプルコード

echo -n "bar" | md5sum

-nは、このエコーの後に改行を入れないことを示すために使用されます。

2番目のサンプル

echo "bar" -n | md5sum

-nをリテラルテキストとして扱っています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.