GNU/Linux >> Linux Esercitazione >  >> Linux

Espressione aritmetica nel reindirizzamento

Non ho una citazione concreta per il perché questo comportamento esiste, ma uscendo dalle note in SC2257* ci sono alcuni punti interessanti da notare nel manuale.

Quando un semplice comando diverso da una funzione incorporata o di shell deve essere eseguito, viene richiamato in un ambiente di esecuzione separato
§3.7.3 Ambiente di esecuzione dei comandi

Ciò riflette quanto notato da SC2257, anche se non è chiaro in quale ambiente venga valutato il valore del reindirizzamento. Tuttavia §3.1.1 Shell Operation sembra dire che il reindirizzamento avviene prima questo (sotto)ambiente di esecuzione viene richiamato:

Fondamentalmente, la shell fa quanto segue:
...

  1. Esegue le varie espansioni della shell....
  2. Esegue tutti i reindirizzamenti necessari e rimuove gli operatori di reindirizzamento e i relativi operandi dall'elenco degli argomenti.
  3. Esegue il comando.

Possiamo vedere che questo non è limitato alle espansioni aritmetiche ma anche ad altre espansioni che cambiano lo stato come := :

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

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

È interessante notare che questo non sembra essere un ambiente subshell (ben definito), perché BASH_SUBSHELL rimane impostato su 0 :

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

Possiamo anche controllare altre shell e vedere che zsh ha lo stesso comportamento, sebbene dash non:

$ 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

Ho scremato il zsh guide ma non ho trovato neanche una menzione esatta di questo comportamento.

Inutile dirlo , questo non sembra essere un comportamento ben documentato, quindi è una fortuna che ShellCheck possa aiutarci a rilevarlo. Tuttavia sembra essere un comportamento di vecchia data, è riproducibile in Bash 3, 4 e 5.

* Sfortunatamente il commit che ha aggiunto SC2257 non si collega a un problema o a qualsiasi altro ulteriore contesto.


Il consiglio di Shellcheck è valido; a volte i reindirizzamenti vengono eseguiti in subshell. Tuttavia, il punto cruciale di questo comportamento è quando si verificano espansioni:

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         

Quando viene chiamato execute_disk_command(), esegue il fork e quindi esegue date(1). Dopo fork() e prima di execve(), vengono eseguiti i reindirizzamenti e le espansioni aggiuntive (tramite do_redirections()). Le variabili espanse e vincolate post-fork non si rifletteranno nella shell madre.

Dal punto di vista di BASH, tuttavia, questo è solo un semplice comando piuttosto che un comando subshell. Questa è una subshell implicita.

Vedere 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.

(riferimenti presi da commit 9e49d343e3cd7e20dad1b86ebfb764e8027596a7 [browse tree])


Linux
  1. Utilizzare $[ Espr ] invece di $(( Espr ))?

  2. Il reindirizzamento a un nome di file Globbed non riesce?

  3. La definizione di un'espressione regolare?

  4. Parentesi nell'aritmetica espr:3 * (2 + 1)?

  5. Prestazioni aritmetiche a 32 bit rispetto a 64 bit

Spiegazione delle operazioni matematiche di Bash (aritmetica di Bash).

Espressione sequenza Bash (intervallo)

Reindirizzamento input/output in Linux/Unix

Spiegazione del reindirizzamento di input e output su Linux

gzip - reindirizzamento o piping?

Risolutore di espressioni da riga di comando?