GNU/Linux >> Linux の 問題 >  >> Linux

リダイレクトの算術式

理由の具体的な引用はありません この動作は存在しますが、SC2257 の注記から外れている* マニュアルには注意すべき興味深い点がいくつかあります。

<ブロック引用>

組み込みまたはシェル関数以外の単純なコマンドの場合 実行される場合、別の実行環境で呼び出されます
§3.7.3 コマンド実行環境

これは、SC2257 の注意事項を反映していますが、リダイレクトの値が評価される環境については不明です。ただし、§3.1.1 シェル操作では、リダイレクトが に発生すると述べているようです。 この実行 (サブ) 環境が呼び出されます:

<ブロック引用>

基本的に、シェルは次のことを行います。
...

  1. さまざまなシェル拡張を実行します....
  2. 必要なリダイレクトを実行し、リダイレクト演算子とそのオペランドを引数リストから削除します。
  3. コマンドを実行します。

これは算術展開だけでなく、 := のような状態を変更する他の展開でも同様であることがわかります。 :

$ 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 [ブラウズ ツリー] からの参照)


Linux
  1. リダイレクションの使い方を覚える方法は?

  2. Expr算術の括弧:3 *(2 + 1)?

  3. grep 式を反転する方法

  1. 32 ビット演算と 64 ビット演算のパフォーマンス

  2. gzip - リダイレクトまたはパイピング?

  3. コマンドライン式ソルバー?

  1. Linux/Unixでの入力/出力リダイレクト

  2. $((Expr))の代わりに$ [Expr]を使用しますか?

  3. sed による正規表現