BashやZshなどのシェルに関して、UnixやLinux、および「バックティックが廃止された」という表現を使用する他のサイトでは、このコメントを何度も目にしました。
このステートメントは正しいですか、それとも間違っていますか?
「廃止予定」には2つの異なる意味があります。
非推奨:(主にソフトウェア機能の)使用可能ですが、通常は置き換えられているため、廃止され、最善の方法で回避されます。
—新しいオックスフォードのアメリカの辞書
この定義により、バッククォートは廃止されました。
非推奨のステータスも機能が将来削除されることを示す場合があります。
— ウィキペディア
この定義により、バッククォートは非推奨ではありません。
シェルコマンド言語のオープングループ仕様 、特にセクション「2.6.3コマンド置換」を引用すると、コマンド置換の両方の形式、バッククォート(_`..cmd..`
_)またはドル括弧( $(..cmd..)
)は、仕様に関する限り、引き続きサポートされます。
抜粋
コマンド置換により、コマンド名自体の代わりにコマンドの出力を置換できます。コマンドが次のように囲まれている場合、コマンド置換が発生します。
_$(command) or (backquoted version): `command`
_シェルは、サブシェル環境(シェル実行環境を参照)でコマンドを実行し、コマンド置換(コマンドのテキストと囲み
$()
またはバッククォート)をコマンドの標準出力で置き換えることにより、コマンド置換を拡張します。 、置換の最後にある1つ以上の<改行>文字のシーケンスを削除します。出力の最後の前に埋め込まれた<改行>文字は削除されません。ただし、IFSの値と有効な引用に応じて、フィールド区切り文字として扱われ、フィールド分割中に削除される場合があります。出力にnullバイトが含まれている場合の動作は規定されていません。コマンド置換のバッククォートスタイル内では、<backslash>は、 '$'、 '_
\`
_'、または<backslash>。一致する逆引用符の検索は、最初の引用符で囲まれていない、エスケープされていない逆引用符で満たされます。この検索中に、シェルコメント、ヒアドキュメント、$(command)
フォームの埋め込みコマンド置換、または引用符付き文字列内でエスケープされていないバッククォートが検出されると、未定義の結果が発生します。 "_`...`
_"シーケンス内で開始するが終了しない一重引用符または二重引用符付きの文字列は、未定義の結果を生成します。
$(command)
形式では、左括弧とそれに続く右括弧の後に続くすべての文字がコマンドを構成します。コマンドに有効なシェルスクリプトを使用できますが、指定されていない結果を生成するリダイレクトのみで構成されるスクリプトは除きます。
ほとんどのユースケースはである必要があるため、バッククォートの代わりにドル括弧形式を使用します。 (上記の第一の意味で非推奨です。)最も評判の良いサイト(U&Lを含む)の多くは、これも同様に説明していることが多いため、適切なアドバイスです。このアドバイスは、シェルからバックティックのサポートを削除するための存在しない計画と混同しないでください。
BashFAQ#082-なぜ$(...)が `...`(バッククォート)よりも優先されるのですか?
抜粋
_
`...`
_は、非常に古い非POSIX互換のボーンシェルのみが必要とするレガシー構文です。常に$(...)
構文を使用する理由はいくつかあります。...
抜粋
これは コマンド置換 の古いBourne互換形式です。 _
`COMMANDS`
_と$(COMMANDS)
の両方の構文はPOSIXで指定されていますが、後者は非常に好ましいですが、前者は残念ながらスクリプトで非常に普及しています。新しいスタイルのコマンド置換は、すべての最新のシェル(および一部)によって広く実装されています。バックティックを使用する唯一の理由は、本物のBourne Shell(Heirloomなど)との互換性のためです。入れ子の場合、バックティックコマンドの置換には特別なエスケープが必要であり、実際に使用されている例は不適切に引用されることが多くなっています。参照: なぜ$(...)が `...`(バッククォート)よりも好ましいのですか? 。
抜粋
これらの一貫性のない動作のため、コマンド置換をネストする、または複雑なスクリプトを埋め込もうとする新しいアプリケーションでは、バッククォートされたさまざまなコマンド置換は推奨されません。
注:この3番目の抜粋(上記)は、バッククォートが機能しないいくつかの状況を示していますが、新しいドル括弧メソッドは、次の段落:
さらに、バッククォート構文には、埋め込みコマンドの内容に対する歴史的な制限があります。新しい "$()"フォームは、あらゆる種類の有効な埋め込みスクリプトを処理できますが、バッククォートされたフォームは、バッククォートを含む一部の有効なスクリプトを処理できません。
そのセクションを読み続けると、バッククォートを使用して失敗する方法を示す失敗が強調表示されますが、新しいドル括弧表記を使用して作業を行います。
したがって、バッククォートの代わりにドル括弧を使用するのが望ましいですが、「これは計画的な時点で完全に機能しなくなる」のように、実際には技術的に「非推奨」になっているものを使用していません。
これらすべてを読んだ後、特に実際の元の非POSIXボーンシェルとの互換性が必要でない限り、ドル括弧を使用することを強くお勧めします。
廃止予定ではありませんが、バッククォート(`...`
)は、POSIX互換ではない最も古いボーンシェルだけが必要とするレガシー構文であり、$(...)
はPOSIXであり、いくつかの理由により推奨されています。
バックティック内のバックスラッシュ(\
)は、明白ではない方法で処理されます。
$ echo "`echo \\a`" "$(echo \\a)"
a \a
$ echo "`echo \\\\a`" "$(echo \\\\a)"
\a \\a
# Note that this is true for *single quotes* too!
$ foo=`echo '\\'`; bar=$(echo '\\'); echo "foo is $foo, bar is $bar"
foo is \, bar is \\
$()
内のネストされた引用ははるかに便利です:
echo "x is $(sed ... <<<"$y")"
の代わりに:
echo "x is `sed ... <<<\"$y\"`"
または次のようなものを書く:
IPs_inna_string=`awk "/\`cat /etc/myname\`/"'{print $1}' /etc/hosts`
$()
は引用にまったく新しいコンテキストを使用するため
bourneシェルとKornシェルはこれらのバックスラッシュを必要とするため、移植性はありませんが、Bashとdashは必要ありません。
コマンド置換をネストするための構文はより簡単です:
x=$(grep "$(dirname "$path")" file)
より:
x=`grep "\`dirname \"$path\"\`" file`
$()
は引用のための完全に新しいコンテキストを適用するため、各コマンド置換は保護され、引用とエスケープに関する特別な懸念なしに単独で処理できます。バックティックを使用すると、2つ以上のレベルの後で醜くなります。
いくつかの例:
echo `echo `ls`` # INCORRECT
echo `echo \`ls\`` # CORRECT
echo $(echo $(ls)) # CORRECT
逆引用符を使用する場合の一貫性のない動作の問題を解決します。
echo '\$x'
出力\$x
echo `echo '\$x'`
出力$x
echo $(echo '\$x')
出力\$x
バックティック構文は、埋め込みコマンドの内容に歴史的な制限があり、バッククォートを含む一部の有効なスクリプトを処理できませんが、新しい$()
フォームは、あらゆる種類の有効な埋め込みスクリプトを処理できます。
たとえば、これらのその他の有効な埋め込みスクリプトは左側の列では機能しませんが、右側では機能します[〜#〜] ieee [〜#〜]:
echo ` echo $(
cat <<\eof cat <<\eof
a here-doc with ` a here-doc with )
eof eof
` )
echo ` echo $(
echo abc # a comment with ` echo abc # a comment with )
` )
echo ` echo $(
echo '`' echo ')'
` )
したがって、$
- prefixed コマンド置換 の構文は、明確な構文で視覚的に明確であるため(人間とマシンの読みやすさが向上します)、ネスト可能で直感的で、内部の解析は分離されています。また、(二重引用符内から解析される他のすべての展開と)一貫性があり、バッククォートが唯一の例外であり、`
に隣接しているときに"
文字が簡単に偽装され、特に小さいフォントや珍しいフォントでは読みにくくなります。
ソース: BashFAQで$(...)
が`...`
(バッククォート)よりも優先される理由
以下も参照してください。