GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Arithmetischer Ausdruck in der Umleitung

Ich habe kein konkretes Zitat für warum Dieses Verhalten existiert, aber abgesehen von den Anmerkungen in SC2257* gibt es einige interessante Punkte, die im Handbuch zu beachten sind.

Wenn ein einfacher Befehl anders als eine eingebaute oder Shell-Funktion ist ausgeführt werden soll, wird es in einer separaten Ausführungsumgebung aufgerufen
§3.7.3 Befehlsausführungsumgebung

Dies spiegelt die Anmerkungen von SC2257 wider, obwohl unklar ist, in welcher Umgebung der Wert der Umleitung ausgewertet wird. §3.1.1 Shell Operation scheint jedoch zu sagen, dass die Umleitung vorher erfolgt Diese Ausführungs-(Unter-)Umgebung wird aufgerufen:

Grundsätzlich macht die Shell Folgendes:
...

  1. Führt die verschiedenen Shell-Erweiterungen durch....
  2. Führt alle erforderlichen Umleitungen durch und entfernt die Umleitungsoperatoren und ihre Operanden aus der Argumentliste.
  3. Führt den Befehl aus.

Wir können sehen, dass dies nicht auf arithmetische Erweiterungen beschränkt ist, sondern auch auf andere zustandsändernde Erweiterungen wie := :

$ bash -c 'date >"${word:=wow}.txt"; echo "word=${word}"'
word=

$ bash -c 'echo >"${word:=wow}.txt"; echo "word=${word}"'
word=wow

Interessanterweise scheint dies keine (wohldefinierte) Subshell-Umgebung zu sein, weil BASH_SUBSHELL bleibt auf 0 gesetzt :

$ date >"${word:=$BASH_SUBSHELL}.txt"; ls
0.txt

Wir können auch einige andere Shells überprüfen und sehen, dass zsh hat das gleiche Verhalten, obwohl dash nicht:

$ 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

Ich habe den zsh überflogen Guide, fand dort aber auch keine genaue Erwähnung dieses Verhaltens.

Unnötig zu sagen , scheint dies kein gut dokumentiertes Verhalten zu sein, daher ist es ein Glück, dass ShellCheck helfen kann, es zu erkennen. Es scheint jedoch ein langjähriges Verhalten zu sein, es ist in Bash 3, 4 und 5 reproduzierbar.

* Leider verlinkt der Commit, der SC2257 hinzugefügt hat, nicht auf ein Problem oder einen anderen weiteren Kontext.


Der Rat von Shellcheck ist vernünftig; manchmal werden Umleitungen in Subshells durchgeführt. Der springende Punkt bei diesem Verhalten ist jedoch wann Erweiterungen auftreten:

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         

Wenn execute_disk_command() aufgerufen wird, verzweigt es sich und führt dann date(1) aus. Nach dem fork() und vor dem execve() werden Umleitungen und zusätzliche Erweiterungen durchgeführt (über do_redirections()). Erweiterte und gebundene Post-Fork-Variablen spiegeln sich nicht in der übergeordneten Shell wider.

Aus Sicht von BASH ist dies jedoch eher ein einfacher Befehl als ein Subshell-Befehl. Dies ist eine implizite Subshell.

Siehe execute_disk_command() in execute_cmd.c

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.

(Verweise aus Commit 9e49d343e3cd7e20dad1b86ebfb764e8027596a7 [Browse Tree])


Linux
  1. Verwenden Sie $[Ausdr] anstelle von $((Ausdr))?

  2. Wie kann man sich merken, wie man die Umleitung verwendet?

  3. Bash + Name durch regulären Ausdruck überprüfen?

  4. Bash TCP-Umleitung Ende der Übertragung?

  5. 6 Beispiele für bedingte Bash-Ausdrücke ( -e, -eq, -z, !=, [, [[ ..)

Bash Math Operationen (Bash Arithmetik) erklärt

Bash-Sequenzausdruck (Bereich)

Eingabe-Ausgabe-Umleitung unter Linux erklärt

Klammer In Expr Arithmetik:3 * (2 + 1)?

So invertieren Sie einen grep-Ausdruck

Regulärer Ausdruck mit sed