GNU/Linux >> Tutoriels Linux >  >> Linux

Expression arithmétique dans la redirection

Je n'ai pas de citation concrète pour pourquoi ce comportement existe, mais en partant des notes dans SC2257*, il y a quelques points intéressants à noter dans le manuel.

Lorsqu'une simple commande autre qu'une fonction intégrée ou shell doit être exécuté, il est appelé dans un environnement d'exécution séparé
§3.7.3 Environnement d'exécution des commandes

Cela reflète ce que SC2257 note, bien qu'il ne soit pas clair dans quel environnement la valeur de redirection est évaluée. Cependant, §3.1.1 Shell Operation semble dire que la redirection se produit avant ce (sous)environnement d'exécution est appelé :

Fondamentalement, le shell effectue les opérations suivantes :
...

  1. Effectue les différentes extensions du shell....
  2. Effectue toutes les redirections nécessaires et supprime les opérateurs de redirection et leurs opérandes de la liste d'arguments.
  3. Exécute la commande.

Nous pouvons voir que cela ne se limite pas aux extensions arithmétiques mais aussi à d'autres extensions à changement d'état comme := :

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

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

Fait intéressant, cela ne semble pas être un environnement de sous-shell (bien défini), car BASH_SUBSHELL reste réglé sur 0 :

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

Nous pouvons également vérifier d'autres shells et voir que zsh a le même comportement, bien que dash ne :

$ 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

J'ai survolé le zsh guide, mais je n'y ai pas non plus trouvé de mention exacte de ce comportement.

Inutile de dire , cela ne semble pas être un comportement bien documenté, il est donc heureux que ShellCheck puisse aider à le détecter. Cela semble cependant être un comportement de longue date, il est reproductible dans Bash 3, 4 et 5.

* Malheureusement, le commit qui a ajouté SC2257 n'est pas lié à un problème ou à tout autre contexte supplémentaire.


Les conseils de Shellcheck sont judicieux ; parfois les redirections sont effectuées dans des sous-shells. Cependant, le nœud de ce comportement est lorsque des expansions se produisent :

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         

Quand execute_disk_command() est appelé, il bifurque puis exécute date(1). Après le fork() et avant le execve(), les redirections et les extensions supplémentaires sont effectuées (via do_redirections()). Les variables développées et liées post-fork ne seront pas reflétées dans le shell parent.

Du point de vue de BASH, cependant, il ne s'agit que d'une simple commande plutôt que d'une commande de sous-shell. Ceci est un sous-shell implicite.

Voir execute_disk_command() dans 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.

(références extraites du commit 9e49d343e3cd7e20dad1b86ebfb764e8027596a7 [parcourir l'arborescence])


Linux
  1. Utiliser $[Expr] au lieu de $((Expr)) ?

  2. La redirection vers un nom de fichier global échoue ?

  3. La définition d'une expression régulière ?

  4. Bash + Vérifier le nom par expression régulière ?

  5. Fin de transmission de la redirection Bash Tcp ?

Explication des opérations mathématiques bash (arithmétique bash)

Expression de séquence bash (plage)

Explication de la redirection d'entrée-sortie sur Linux

6 Exemples d'expressions conditionnelles Bash ( -e, -eq, -z, !=, [, [[ ..)

gzip - redirection ou tuyauterie ?

Expression régulière avec sed