
私はbash(GNU bash、バージョン4.4.20(1)-release(i686-pc-linux-gnu))のシェル拡張を理解しようとしています。
私の対話型bashシェル型から
x='$(id)'
$x
$(echo $x)
最後の 2 行のいずれかで、次の形式のエラーが発生すると予想されます。
bash: uid=xxx(user): command not found
しかし、得た
bash: $(id): command not found
。
ここでコマンド置換がなぜ起こらないのか理解できません。変数拡張によって達成すべきではないでしょうか?私の考えでは、ここで説明されているようにShell操作に関連しているようです。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
コマンドは(echo
明らかに)、/none/@(id)
( globパターン/none/@(id)
が何も一致しないので変更されていないまま)、/usr/bin/id
(globパターンが/usr/bin/@(id)
ファイルと一致するので変更されていない)の3つの単語で拡張されます。一致する単一要素のリスト)。
bashのマニュアルでは、関連文は次のとおりです。シェル拡張部分。
拡張順序は、中かっこ拡張、引数と変数拡張、算術拡張、コマンド置換(左から右へ)です。
2つのセミコロンの間のすべての内容は一度に渡されます。各パスは前のパスの結果に基づいています。
単一の文章(上記で引用した文章と同じくらい複雑な文章でも)で全体の話を伝えることはできません。シェルセマンティクスは複雑です。私はどのシェルのマニュアルにも特別なケースの詳細がすべて含まれているかどうか疑問に思います。これ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".