コマンド置換を含む bash の変数

コマンド置換を含む bash の変数

私は、bash (GNU bash、バージョン 4.4.20(1) リリース (i686-pc-linux-gnu)) のシェル拡張を理解しようとしています。

インタラクティブなbashシェルに入力する

x='$(id)'
$x
$(echo $x)

最後の2行のいずれかに次のようなエラーが出ると予想していました。

bash: uid=xxx(user): command not found

しかし

bash: $(id): command not found

ここでコマンド置換が行われない理由がわかりません。変数の展開後に実現されるべきではないでしょうか? 私の推測では、ここで説明されているシェル操作に関係していると思います。https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Operation

誰かこの動作を説明できますか?

私は、bash の拡張をより正確に理解することに興味があるだけです。私の質問では、実際のスクリプトを実行することには興味がありません。

答え1

$(…)はコマンド置換です (「プロセス置換」は<(…)など)。変数置換とコマンド置換は、文字列の左から右へ同じパスで発生します。これらの置換の結果で発生するのは、単語の分割とグロブのみです。

したがって、は5 文字の文字列 にx='$(id)'設定されます。次に、 を実行するために、シェルは を値 に置き換えます。これには空白やグロブ文字が含まれていないため、コマンド名として扱われます。x$(id)$x$x$(id)

以下と対比:

x='@(id)'
shopt -s extglob
echo /none/$x /usr/bin/$x

ファイルが/none/id存在しないが、/usr/bin/id存在すると仮定すると、echoコマンドは 3 つの単語に展開されます: echo(当然)、/none/@(id)(glob パターンは/none/@(id)何も一致しないため、変更されません)、/usr/bin/id(glob パターンは/usr/bin/@(id)1 つのファイルに一致するため、1 要素の一致リストに置き換えられます)。

bashマニュアルでは、関連する文章はシェル拡張セクション。

展開の順序は、中括弧展開、チルダ展開、パラメータと変数の展開、算術展開、コマンド置換(左から右に実行)、単語分割、ファイル名展開です。

2 つのセミコロンの間にあるものはすべて 1 つのパスです。各パスは、前のパスの結果に基づいて動作します。

1つの文(上記で引用したような複雑な文でも)では、すべてを説明できないことに注意してください。シェルのセマンティクスは複雑です。どのシェルのマニュアルにも、すべてのコーナーケースの詳細が記載されているとは思えません。POSIX仕様より正式ですが、bash 固有の拡張機能はカバーされておらず、いくつかの非常に奇妙なケースは未定義のままになっています。

答え2

それは引用です。一重引用符 ( ') はリテラル文字列を定義し、補間やエスケープは発生しません。二重引用符 ( ") は補間とエスケープを可能にします。

次に例を示します。

$ x='$(id)'
$ echo 'The variable x contains the value \"$x\"'
The variable x contains the value \"$x\"
$ echo "The variable x contains the value \"$x\""
The variable x contains the value "$(id)"

$ x="$(id)"
$ echo "The variable x contains the value \"$x\""
The variable x contains the value "uid=1000(myusername)..."

以下は、一重引用符と二重引用符に基づく補間とエスケープの別の例です。

$ echo 'The current directory is $PWD according to the variable \"\$PWD\".'
The current directory is $PWD according to the variable \"\$PWD\".

$ echo "The current directory is $PWD according to the variable \"\$PWD\"."
The current directory is /tmp according to the variable "$PWD".

関連情報