¿Es posible shift
asignar un valor a un parámetro de matriz desde dentro de una subcapa?
Código de ejemplo:
arr=(a b c)
(shift arr)
echo $arr
# prints: a b c
# should print: b c
Respuesta1
El objetivo de los subshells es ejecutar una parte del código en una copia del actual.entorno de ejecución de shell(ver detalles enla especificación POSIXfor sh
), para preservar el original, por lo que el punto es que cualquier cambio en las variables realizadas en el subnivel se perderá después de la terminación del subnivel.
Tradicionalmente, esto se hace mediante el shell que bifurca un proceso y ejecuta el código en el hijo mientras el padre espera su terminación.
POSIX no exige eso y ksh93 al menos implementa (...)
subcapas restaurando cuidadosamente el entorno original al regresar la subcapa sin bifurcar un proceso si eso se puede evitar (aunque a veces no lo hace correctamente en algunos casos extremos).
zsh
bifurca un proceso para eso como la mayoría de los otros shells. Hay excepciones para la optimización, como cuando un (...)
subshell es el último comando en un zsh -c
script:
$ zsh -c 'zmodload zsh/system; echo $$; (echo $sysparams[pid]; ps; ps)'
21085
21085
PID TTY TIME CMD
1839 pts/4 00:00:00 zsh
21085 pts/4 00:00:00 zsh
21086 pts/4 00:00:00 ps
PID TTY TIME CMD
1839 pts/4 00:00:00 zsh
21085 pts/4 00:00:00 ps
Es el mismo proceso 21085 anterior que ejecutó zsh
, interpretó el subshell e incluso ejecutó el último ps
comando.
Es suficiente configurar a trap
para invalidar esa optimización, el punto es que solo se hace si zsh puede garantizar que el shell no ejecutará nada después de que regrese el subshell.
Para que el proceso hijo pueda cambiar el valor de una variable en el proceso padre, necesitaría hacer cosas como adjuntarse gdb
a ese proceso e inyectar código en él para cambiar las estructuras de la memoria interna en ese proceso.
Si desea obtener el valor de una matriz definida por un subshell, necesitaría que el subshell pase su definición al padre. Esto podría ser, por ejemplo, a través de:
eval "$(
# also a subshell using $(...)
arr=( a b c )
typeset -p arr
)"
Luego typeset
generará typeset -a arr=( a b c )
(o typeset -g -a arr=( a b c )
si se llama dentro de una función), que una vez eval
activada hará que se cree la misma variable en el padre.
Por cierto, en lugar de:
shift arr
Yo usaría:
shift 1 arr
o:
arr[1]=()
El shift arr
fragmento de código es ambiguo ya que significa cosas diferentes ( shift 1 arr
vs shift arr argv
) dependiendo de si arr
se declara como una variable de matriz o no. El uso shift 1 arr
hace que sea más obvio que lo que quieres es lo primero.
Respuesta2
Una subcapa es un proceso diferente, no puede modificar el proceso principal.