理由の具体的な引用はありません この動作は存在しますが、SC2257 の注記から外れている* マニュアルには注意すべき興味深い点がいくつかあります。
<ブロック引用>
組み込みまたはシェル関数以外の単純なコマンドの場合 実行される場合、別の実行環境で呼び出されます
§3.7.3 コマンド実行環境
これは、SC2257 の注意事項を反映していますが、リダイレクトの値が評価される環境については不明です。ただし、§3.1.1 シェル操作では、リダイレクトが 前 に発生すると述べているようです。 この実行 (サブ) 環境が呼び出されます:
<ブロック引用>
基本的に、シェルは次のことを行います。
...
- さまざまなシェル拡張を実行します....
- 必要なリダイレクトを実行し、リダイレクト演算子とそのオペランドを引数リストから削除します。
- コマンドを実行します。
これは算術展開だけでなく、 :=
のような状態を変更する他の展開でも同様であることがわかります。 :
$ bash -c 'date >"${word:=wow}.txt"; echo "word=${word}"'
word=
$ bash -c 'echo >"${word:=wow}.txt"; echo "word=${word}"'
word=wow
興味深いことに、これは (明確に定義された) サブシェル環境ではないようです。なぜなら BASH_SUBSHELL
0
に設定されたまま :
$ date >"${word:=$BASH_SUBSHELL}.txt"; ls
0.txt
他のいくつかのシェルも確認でき、zsh
であることがわかります。 dash
でも同じ動作をします しません:
$ zsh -c 'date >"${word:=wow}.txt"; echo "word=${word}"'
word=
$ zsh -c 'echo >"${word:=wow}.txt"; echo "word=${word}"'
word=wow
$ dash -c 'date >"${word:=wow}.txt"; echo "word=${word}"'
word=wow
$ dash -c 'echo >"${word:=wow}.txt"; echo "word=${word}"'
word=wow
zsh
をすくい取った ガイドに記載されていますが、この動作についての正確な言及も見つかりませんでした.
言うまでもなく 、これは十分に文書化された動作ではないように見えるため、ShellCheck がそれをキャッチするのに役立つことは幸運です。ただし、これは長年の動作のようで、Bash 3、4、および 5 で再現可能です。
* 残念ながら、SC2257 を追加したコミットは問題やその他のコンテキストにリンクしていません。
Shellcheck のアドバイスは適切です。サブシェルでリダイレクトが実行されることがあります。ただし、この動作の核心はいつかということです 展開が発生します:
bind_int_variable variables.c:3410 cnt = 2, late binding
expr_bind_variable expr.c:336
exp0 expr.c:1040
exp1 expr.c:1007
exppower expr.c:962
expmuldiv expr.c:887
exp3 expr.c:861
expshift expr.c:837
exp4 expr.c:807
exp5 expr.c:785
expband expr.c:767
expbxor expr.c:748
expbor expr.c:729
expland expr.c:702
explor expr.c:674
expcond expr.c:627
expassign expr.c:512
expcomma expr.c:492
subexpr expr.c:474
evalexp expr.c:439
param_expand subst.c:9498 parameter expansion, including arith subst
expand_word_internal subst.c:9990
shell_expand_word_list subst.c:11335
expand_word_list_internal subst.c:11459
expand_words_no_vars subst.c:10988
redirection_expand redir.c:287 expansions post-fork()
do_redirection_internal redir.c:844
do_redirections redir.c:230 redirections are done in child process
execute_disk_command execute_cmd.c:5418 fork to run date(1)
execute_simple_command execute_cmd.c:4547
execute_command_internal execute_cmd.c:842
execute_command execute_cmd.c:394
reader_loop eval.c:175
main shell.c:805
execute_disk_command() が呼び出されると、分岐してから date(1) を実行します。 fork() の後、execve() の前に、リダイレクトと追加の拡張が行われます (do_redirections() を介して)。フォーク後に展開およびバインドされた変数は、親シェルには反映されません。
ただし、BASH の観点からは、これはサブシェル コマンドではなく単純なコマンドです。これは暗黙のサブシェルです。
execute_cmd.c の execute_disk_command() を参照
Execute a simple command that is hopefully defined in a disk file
somewhere.
1) fork ()
2) connect pipes
3) look up the command
4) do redirections
5) execve ()
6) If the execve failed, see if the file has executable mode set.
If so, and it isn't a directory, then execute its contents as
a shell script.
(コミット 9e49d343e3cd7e20dad1b86ebfb764e8027596a7 [ブラウズ ツリー] からの参照)