GNU/Linux >> Tutoriales Linux >  >> Linux

Expresión aritmética en redirección

No tengo una cita concreta para por qué este comportamiento existe, pero saliendo de las notas en SC2257* hay algunos puntos interesantes a tener en cuenta en el manual.

Cuando un comando simple que no sea una función incorporada o de shell se va a ejecutar, se invoca en un entorno de ejecución separado
§3.7.3 Entorno de ejecución de comandos

Esto refleja lo que señala SC2257, aunque no está claro en qué entorno se evalúa el valor de la redirección. Sin embargo, §3.1.1 Operación Shell parece decir que la redirección ocurre antes se invoca este (sub)entorno de ejecución:

Básicamente, el shell hace lo siguiente:
...

  1. Realiza las diversas expansiones de shell....
  2. Realiza las redirecciones necesarias y elimina los operadores de redirección y sus operandos de la lista de argumentos.
  3. Ejecuta el comando.

Podemos ver que esto no se limita a las expansiones aritméticas sino también a otras expansiones que cambian de estado como := :

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

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

Curiosamente, esto no parece ser un entorno de subcapa (bien definido), porque BASH_SUBSHELL permanece establecido en 0 :

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

También podemos verificar algunos otros shells y ver que zsh tiene el mismo comportamiento, aunque dash no:

$ 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

Leí el zsh pero tampoco encontré una mención exacta de este comportamiento allí.

No hace falta decir , este no parece ser un comportamiento bien documentado, por lo que es una suerte que ShellCheck pueda ayudar a detectarlo. Sin embargo, parece ser un comportamiento de larga data, es reproducible en Bash 3, 4 y 5.

* Desafortunadamente, la confirmación que agregó SC2257 no se vincula a un problema ni a ningún otro contexto adicional.


El consejo de Shellcheck es sensato; a veces, las redirecciones se realizan en subcapas. Sin embargo, el quid de este comportamiento es cuando se producen expansiones:

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         

Cuando se llama a execute_disk_command(), se bifurca y luego ejecuta date(1). Después de fork() y antes de execve(), se realizan redirecciones y expansiones adicionales (a través de do_redirections()). Las variables expandidas y vinculadas después de la bifurcación no se reflejarán en el shell principal.

Sin embargo, desde la perspectiva de BASH, este es solo un comando simple en lugar de un comando de subcapa. Esta es una subcapa implícita.

Ver execute_disk_command() en 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.

(referencias tomadas de commit 9e49d343e3cd7e20dad1b86ebfb764e8027596a7 [navegar árbol])


Linux
  1. ¿La redirección a un nombre de archivo global falla?

  2. ¿La definición de una expresión regular?

  3. Bash + Verificar nombre por expresión regular?

  4. Bash Tcp Redirección ¿Fin de la transmisión?

  5. 6 ejemplos de expresiones condicionales de Bash (-e, -eq, -z, !=, [, [[ ..)

Explicación de las operaciones matemáticas de Bash (aritmética de Bash)

Expresión de secuencia Bash (rango)

Explicación de la redirección de entrada y salida en Linux

Paréntesis en aritmética Expr:3 * (2 + 1)?

Cómo invertir una expresión grep

Rendimiento Aritmética de 32 bits frente a 64 bits