Bashのプログラミングブックで同様の例を読んだ。
$ cat indirection
#!/usr/bin/env bash
set -x
num=1
eval "${!num#*:}"
$
スクリプトを実行すると、bash indirection "test:echo blah"
スクリプトの最後の行はどのように処理されますか?間接参照が最初に発生すると思っeval "${!num#*:}"
たらeval "${1#*:}"
?その後、部分文字列は削除されeval "${1#*:}"
ますかeval echo blah
?それではなぜeval
必要なのでしょうか?つまり、${!num#*:}
置き換えるとeval "${!num#*:}"
同じ結果が得られますか?
答え1
パラメータ拡張の出力は次のとおりです。
$ echo "${1#*:}"
echo blah
はい、そうです。この特別なケースでは、次のようになります。
$ set -- "test:echo blah"
$ eval "${1#*:}"
blah
$ ${1#*:}
blah
同じコマンドを実行してください。しかし、これは必ずしも真実ではありません。
$ "${1#*:}"
bash: echo blah: command not found
実際、シェルメタ文字を含む文字列は、引用符なしで正しく機能しません。
$ set -- "test:echo blah > file"
${1#*:}
blah > file
ただし、リダイレクトは発生しません(ファイルが生成されます)。
$ eval "${1#*:}"
fileというファイルがPWDに生成されます。