2016-01-14 19 views
5

Sono confuso tra i due.

Mentre la variabile interna $ BASH_SUBSHELL indica il livello di annidamento di una subshell, la variabile $ SHLVL mostra nessun cambiamento all'interno di una subshell.

Che cosa significa esattamente? Se apro una shell in un'altra shell, il valore di $ SHLVL aumenta. Non è una sottotitola?

risposta

7

No, in esecuzione manualmente una nuova shell (via /bin/sh o /bin/bash etc.) non è una subshell in questo contesto.

Una sottochiave è quando la shell genera una nuova istanza di shell sul proprio per gestire alcuni lavori.

L'utilizzo di Command Substitution (ad esempio $(command)) è una sottotitolazione (come l'invocazione di vecchi apici inversa).

L'utilizzo di un pipeline (ad esempio echo '5.1+5.3' | bc -l) crea subshell per ciascun componente della pipeline.

L'utilizzo di Process Substitution (ad esempio <(command)) crea una subshell.

Grouping commands (ad esempio (declare a=5; echo $a)) crea una subshell.

L'esecuzione di comandi in the background (ad esempio sleep 1 &) crea una subshell.

Ci possono essere anche altre cose, ma quelle sono casi comuni.

Testing questo è facile:

$ printf "Outside: $BASH_SUBSHELL , $SHLVL\nInside: $(echo $BASH_SUBSHELL , $SHLVL)\n" 
Outside: 0 , 1 
Inside: 1 , 1 
$ (printf "Outside: $BASH_SUBSHELL , $SHLVL\nInside: $(echo $BASH_SUBSHELL , $SHLVL)\n") 
Outside: 1 , 1 
Inside: 2 , 1 
$ bash -c 'printf "Outside: $BASH_SUBSHELL , $SHLVL\nInside: $(echo $BASH_SUBSHELL , $SHLVL)\n"' 
Outside: 0 , 2 
Inside: 1 , 2 
$ bash -c '(printf "Outside: $BASH_SUBSHELL , $SHLVL\nInside: $(echo $BASH_SUBSHELL , $SHLVL)\n")' 
Outside: 1 , 2 
Inside: 2 , 2 

La fonte del tuo preventivo (la generalmente scarsa, e spesso meglio evitato, ABS) dimostra anche questo un po '(e in modo poco chiaro, solo un altro esempio della generale mancanza di rigore e di qualità in quella guida "Avanzate"):

echo " \$BASH_SUBSHELL outside subshell  = $BASH_SUBSHELL"   # 0 
    (echo " \$BASH_SUBSHELL inside subshell  = $BASH_SUBSHELL")  # 1 
    ((echo " \$BASH_SUBSHELL inside nested subshell = $BASH_SUBSHELL")) # 2 
#^^       *** nested ***      ^^ 

echo 

echo " \$SHLVL outside subshell = $SHLVL"  # 3 
(echo " \$SHLVL inside subshell = $SHLVL") # 3 (No change!) 
+0

Grazie mille, mi ha aiutato molto. –

5

$SHLVL:
Livello di shell, quanto profondamente Bash è annidato. Se, alla riga di comando, $ SHLVL è 1, allora in uno script verrà incrementato a 2. Questa variabile non è influenzata da sottotitoli.

$BASH_SUBSHELL:
Una variabile che indica il livello di subshell.

Ecco come avranno valori diversi:

# In the login bash shell 
echo $BASH_SUBSHELL:$SHLVL 
0:1 

# 1st nested child 
bash 
echo $BASH_SUBSHELL:$SHLVL 
0:2 

# 2nd nested child 
bash 
echo $BASH_SUBSHELL:$SHLVL 
0:3 

# back to 1st nested child 
exit 
echo $BASH_SUBSHELL:$SHLVL 
0:2 

# back to parent shell 
exit 
echo $BASH_SUBSHELL:$SHLVL 
0:1 

# first level sub-shell  
(echo $BASH_SUBSHELL:$SHLVL) 
1:1 

# 2nd level sub-shell 
((echo $BASH_SUBSHELL:$SHLVL)) 
2:1 

# 3rd level sub-shell 
(((echo $BASH_SUBSHELL:$SHLVL))) 
3:1 
Problemi correlati