Escopo da variável de controle de loop no shell? [fechadas]

1

Eu tenho uma pergunta sobre for loop in shell.

Vamos supor que esse script de shell simples:

#!/bin/sh
loop() {                                                                                                                                                                                                                                                                                                               
    for i in 1 2 3 4; do                                                                                                                                           
        if [ $i -eq 2 ]; then                                                                                                                                      
            [ $1 -eq 2 ] && return 1                                                                                                                           
            loop $(($1 + 1)) && return 1                                                                                                                     
        fi                                                                                                                                                         
    done                                                                                                                                                           
return 1                                                                                                                                                       
}                                                                                                                                                                  

loop 0       

Todas as variáveis são globais, exceto argumentos (e argumentos de função). Então, se eu quiser uma variável local em função Eu teria que passar isso como argumento.

Eu tentei executar este script simples, mas não tenho certeza se também a lista de loop for (1 2 3 4 neste exemplo) também é local? Veja abaixo:

+ loop 0
+ for i in 1 2 3 4
+ '[' 1 -eq 2 ']'
+ for i in 1 2 3 4
+ '[' 2 -eq 2 ']'
+ '[' 0 -eq 2 ']'
+ loop 1
+ for i in 1 2 3 4
+ '[' 1 -eq 2 ']'
+ for i in 1 2 3 4
+ '[' 2 -eq 2 ']'
+ '[' 1 -eq 2 ']'
+ loop 2
+ for i in 1 2 3 4
+ '[' 1 -eq 2 ']'
+ for i in 1 2 3 4
+ '[' 2 -eq 2 ']'
+ '[' 2 -eq 2 ']'
+ return 1
+ for i in 1 2 3 4
+ '[' 3 -eq 2 ']'
+ for i in 1 2 3 4
+ '[' 4 -eq 2 ']'   <- here is $i == 4
+ return 1
+ for i in 1 2 3 4
+ '[' 3 -eq 2 ']'   <- here is $i == 3, correctly behaving as local variable ...
+ for i in 1 2 3 4
+ '[' 4 -eq 2 ']'
+ return 1

Alguém pode, por favor, me dizer como funciona o loop for internamente? Estou um pouco confuso sobre a lista for loop, que está se comportando como "variável local".

Muito obrigado por todas as suas respostas! :)

    
por Bomba 24.06.2017 / 19:00

2 respostas

1
$ reset() { i=$1; }
$ for i in 1 2 3 4 ; do echo -n "$i "; reset 3; echo "$i" ; done;
1 3
2 3
3 3
4 3

i não é feito em local em reset , portanto, a alteração é visível fora da função. Mas a mudança para i não afeta os valores que i recebe nas seguintes iterações. As palavras listadas no comando for são atribuídas a i , uma por vez, na ordem esperada.

Então, sim, há um "ponteiro oculto" que informa a posição na lista de palavras. Tem que haver, caso contrário, loops com palavras repetidas, como for i in a a a ; do ... não funcionaria. Há i obtém o mesmo valor em cada iteração, mas o loop ainda executa um número fixo de iterações.

    
por 24.06.2017 / 20:49
1

Não sei o que você está tentando fazer, mas

  1. Você nunca return 0 ("true") da função, por isso, nunca retornará até que seja tentada em todas as combinações.
  2. $i não é uma variável local:

    $ foo() { i=1; bar; }
    $ bar() { echo $i; }
    $ foo
    1
    
  3. Você pode querer depurar isso vendo em qual linha cada comando está:

    trap 'printf "$LINENO "' DEBUG
    
  4. $1 é local para cada chamada de função e não é transmitido mesmo quando uma função chama a si mesma:

    $ foo() { if [ $# -ne 0 ]; then echo "One more time"; foo; fi; }
    $ foo 1
    One more time
    

    Este é o caso em todas as principais linguagens de programação de alto nível. Caso contrário, a recursão seria completamente quebrada.

por 24.06.2017 / 20:00