Modifique o parâmetro da matriz de dentro do subshell

Modifique o parâmetro da matriz de dentro do subshell

É possível atribuir shiftou atribuir um valor a um parâmetro de array de dentro de um subshell?

Código de exemplo:

arr=(a b c)
(shift arr)
echo $arr
# prints: a b c
# should print: b c

Responder1

É o objetivo dos subshells, executar uma parte do código em uma cópia do atualambiente de execução de shell(veja detalhes ema especificação POSIXfor sh), de modo a preservar o original, portanto, o ponto principal é que qualquer alteração nas variáveis ​​​​feita no subshell seria perdida após o término do subshell.

Tradicionalmente, isso é feito pelo shell que bifurca um processo e executa o código no filho enquanto o pai aguarda seu encerramento.

O POSIX não exige isso e o ksh93 pelo menos implementa (...)subshells restaurando cuidadosamente o ambiente original após o retorno do subshell sem bifurcar um processo, se isso puder ser evitado (embora às vezes falhe em fazê-lo corretamente em alguns casos extremos).

zshbifurca um processo para isso, como a maioria dos outros shells. Existem exceções para otimização, como quando um (...)subshell é o último comando em um zsh -cscript:

$ 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

É o mesmo processo 21085 acima que executou zsh, interpretou o subshell e até executou o último pscomando.

É suficiente definir a trappara invalidar essa otimização, a questão é que isso só será feito se zsh puder garantir que nada será executado pelo shell após o retorno do subshell.

Para que o processo filho possa alterar o valor de uma variável no processo pai, ele precisaria fazer coisas como anexar gdba esse processo e injetar código nele para alterar as estruturas de memória interna desse processo.

Se você quisesse obter o valor de um array conforme definido por um subshell, você precisaria que o subshell passasse sua definição para o pai. Isso poderia ser, por exemplo, através de:

eval "$(
  # also a subshell using $(...)
  arr=( a b c )
  typeset -p arr
)"

Então typesetserá gerado typeset -a arr=( a b c )(ou typeset -g -a arr=( a b c )se chamado dentro de uma função), que uma vez evaluado fará com que a mesma variável seja criada no pai.

A propósito, em vez de:

shift arr

Eu usaria:

shift 1 arr

ou:

arr[1]=()

O shift arrtrecho de código é ambíguo, pois significa coisas diferentes ( shift 1 arrvs shift arr argv), dependendo se arré declarado como uma variável de array ou não. O uso shift 1 arrtorna mais óbvio que é o primeiro que você deseja.

Responder2

Um subshell é um processo diferente, não pode modificar o processo pai.

informação relacionada