シェルプログラミングの$(command)と `command`の違いは何ですか?


258

コマンドの出力を変数としてsh / ksh / bashに保存するには、次のいずれかを実行できます。

var=$(command)

または

var=`command`

2つの方法の違いは何ですか?



Gitコーディングガイドラインで詳しく説明されているネストされた問題が見つかります。以下の私の回答を参照してください。
— VonC 2014

回答:


274

のようにそれ自体の中に簡単にネストできる$()ので、コマンド置換の代わりにバックティック/グラビアマークが廃止さ$()れました$(echo foo$(echo bar))。バックスラッシュがバックティック/墓標バージョンでどのように解析されるかなど、他にも違いがあります。

常に$(...)構文を好むいくつかの理由については、BashFAQ / 082を参照してください。

さまざまな違いの詳細については、POSIX仕様も参照してください。


25
良いリンクですが、そのテキストはバッククォートを非難するものではありません$(...) -代替としてそれらを注記するだけです。
— ノーマングレイ

24
@NormanGray POSIXは、廃止されたという言葉を言わないかもしれませんが、それは、廃止された"the backquoted variety of command substitution is not recommended"
— IMHO

11
POSIXはバックティックを廃止しませんでしたが$(...)、代わりの方法として追加されました。バックティックの既知の実装バグはありませんが、の実装バグは多数知られてい$(...) ます。したがって、移植性の問題のために、ネストされていない呼び出しにはバックティックを使用することをお勧めします。$(...)再帰的なパーサーが必要ですが、この機能を導入したksh86では使用されませんでした。 正しい実装のリストについては、in-ulm.de /〜mascheck / various / cmd-substを確認してください。適合シェルは、ケースD.2を除くすべてのケースをサポートする必要があります。
— schily

2
として表示する必要があるPOSIXには他にもありますdeprecated。たとえば、これを使用するとwaitpid()、exit()パラメーターから完全な32ビットが表示されなくなりますが、最近のBourneシェルを除くすべてのシェルは、現在使用可能な呼び出しのwaitpid()代わりに引き続き使用しwaitid()ます。 26年。
— schily

回答のリンクは、バッククォートとの間にいくつかの違いがあることを示しています。これ$()については、ドキュメントのこの部分で詳しく説明しています。違いはネストだけではありません。
— 一部のプログラマー、

39

彼らは同じように動作します。違いは構文的です。ネストする方が簡単$()です``。

listing=$(ls -l $(cat filenames.txt))

対

listing=`ls -l \`cat filenames.txt\``

10
echo $(echo \$abc)と同じではありませんecho `echo \$abc`‍- $(echo \`)との ためにも違いがあります$(echo \\)
— Peter.O

もう1つの違いは、echo foo `#comment`vs echo foo $(#comment)です。2つ目は機能しません。(複数行コマンドでのコメントに使用されます。)
— wisbucky

27

2014年7月:コミットf25f5e6(Elia Pinto(devzero2000)、2014年4月、Git 2.0)により、ネストの問題が追加されます。

バッククォート形式は、コマンド置換の従来の方法であり、POSIXでサポートされています。
ただし、最も単純な使用を除いて、すべてがすぐに複雑になります。
特に、埋め込みコマンドの置換や二重引用符の使用には、バックスラッシュ文字を使用した慎重なエスケープが必要です
。

それがgit / Documentation / CodingGuidelinesが言及している理由です:

$( ... )コマンドの置き換えが望ましい。とは異なり、適切にネストします。
それはボーンが最初からそれを綴った方法であったはずですが、残念ながらそうではありません。

thiton はコメントしました:

だからこそある`echo `foo`` 各ので、固有の曖昧さの一般的でない仕事をしますので、``開閉をすることができます。
運や特別な機能により、特別なケースで機能する場合があります。


2016年1月の更新:Git 2.8(2016年3月)は、バッククォートを完全に削除します。

参照ec1b763をコミットし、9c10377をコミットし、c7b793aをコミットし、80a6b3fコミット、9375dcfをコミットし、e74ef60をコミットし、27fe43eをコミットし、2525c51をコミットし、becd67fコミット、a5c98acをコミットし、8c311f9をコミットし、57da049をコミットし、1d9e86fコミット、78ba28dをコミットし、efa639fコミット、1be2fa0をコミットし、コミット38e9476、コミット8823d2f、コミット32858a0、コミットcd914d8(2016年1月12日)エリア・ピント(devzero2000)。
(による合併Junio C浜野- gitster-でe572fefコミット、2016年1月22日)

Gitの2.8以降から、それがすべてではありません$(...)もう、`...`。


2
$()これはPOSIX仕様でもあります。バックティックが「POSIXでサポートされている」として記述されているため、これが固有のものであることを意味しています。これは、サポートされている構文がバッククォートのみである(1970年代の)POSIX Bourneのみです。
— Charles Duffy

25

古いバックティック形式が使用されている場合、バックスラッシュは、$、 `、または\が後に続く場合を除いて、文字どおりの意味を保持します。バックスラッシュが前にない最初のバックティックは、コマンド置換を終了します。

新しい$(command)形式を使用する場合、括弧内のすべての文字がコマンドを構成します。特別に扱われるものはありません。

両方のフォームを入れ子にすることができますが、バックティックバリエーションには次のフォームが必要です。

`echo \`foo\`` 

とは対照的に:

$(echo $(foo))

1
マイナーな修正。バックティックバージョンとバージョンの両方$()がPOSIXに準拠しています。
— SiegeX、2011年

5

コマンド内で使用できるエスケープされていない文字を除いて、ほとんど違いはありません。さらに複雑な2レベルのコマンド置換を行うために、$(...)コマンド内に(およびその逆に)`...`コマンドを配置することもできます。

バックスラッシュ文字/演算子の解釈は少し異なります。ネスト時に他のものの中で、`...`置換コマンドを、あなたは、内側のエスケープする必要があります`と文字を、\で、一方、$() substitionそれが自動的にネストを理解しています。


0

「2つの方法の違いは何ですか?」

この動作に注意してください:

A="A_VARIABLE"
echo "$(echo "\$A")"
echo "`echo "\$A"`"

次の結果が得られます。

$A
A_VARIABLE

 

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