Di fronte al comando `source`


9

Uso il sourcecomando nel mio script bash per leggere / stampare i valori delle variabili

more linuxmachines_mount_point.txt

export linuxmachine01="sdb sdc sdf sdd sde sdg"
export linuxmachine02="sde sdd sdb sdf sdc"
export linuxmachine03="sdb sdd sdc sde sdf"
export linuxmachine06="sdb sde sdf sdd"

source  linuxmachines_mount_point.txt

echo $linuxmachine01
sdb sdc sdf sdd sde sdg

Qual è l'opposto di sourceper disinserire le variabili?

Risultati aspettati

echo $linuxmachine01

< no output >

14
Non è sourceche sta impostando le variabili nel tuo ambiente, ma le exportistruzioni nel file che tu source. Quindi sourcepotrebbe essere il contrario di source, se hai sourceun file diverso che unsetè tutte le stesse variabili.
user4556274

2
sì, non usare le esportazioni, basta usare name = "val". L'esportazione è per le variabili da script a binari (l'ambiente).
ctrl-d,


2
Questo è impossibile. Il concetto che stai cercando si chiama Reversible Computing . I linguaggi di programmazione devono essere progettati in modo specifico con alcune severe restrizioni per essere reversibili. Bash non è uno di quei linguaggi di programmazione.
Jörg W Mittag,

1
@yael, non è vero (e ovviamente non hai mai eseguito il test che stai dicendo a ctrl-d di fare); non hai assolutamente bisogno della exports. Tutto ciò che exportfa è copiare i valori nell'ambiente, ma sono presenti come variabili di shell anche se sono definiti anche come variabili di ambiente. Inoltre, la definizione di variabili di ambiente non necessarie riduce la lunghezza massima della riga di comando, poiché sono archiviate nello stesso spazio (limitato!) Per processo.
Charles Duffy,

Risposte:


21

Utilizzo di una subshell (consigliata)

Esegui il comando source in una subshell:

(
source linuxmachines_mount_point.txt
cmd1 $linuxmachine02
other_commands_using_variables
etc
)
echo $linuxmachine01  # Will return nothing

Subshell sono definiti da parentesi: (...). Qualsiasi variabile di shell impostata all'interno della subshell viene dimenticata al termine della subshell.

Utilizzando unset

Ciò annulla qualsiasi variabile esportata da linuxmachines_mount_point.txt:

unset $(awk -F'[ =]+' '/^export/{print $2}' linuxmachines_mount_point.txt)
  • -F'[ =]+' dice a awk di usare qualsiasi combinazione di spazi e segni di uguale come separatore di campo.

  • /^export/{print $2}

    Questo dice a awk di selezionare le linee che iniziano con exporte quindi stampare il secondo campo.

  • unset $(...)

    Questo esegue il comando all'interno $(...), acquisisce il suo stdout e annulla qualsiasi variabile denominata dal suo output.


perché non usarlo - per i nel file `awk '{print $ 2}' | awk -F "=" '{print $ 1}' `; disinserire $ i; fatto ? (più semplice per non essere impostato)
yael

2
@yael che utilizza un processo aggiuntivo e un ciclo quando nessuno dei due è necessario. Le opinioni possono variare ma non lo considero più semplice. Inoltre e potenzialmente pericoloso, presuppone che ogni riga in filesia un'istruzione di esportazione.
Giovanni 1024,

8
@yael Inoltre, azzerare le variabili e annullare altri effetti collaterali del codice è esattamente ciò che serve per i subshells. Lo fanno in modo semplice e affidabile. A meno che non ci siano altri motivi particolari, i sottotitoli sono ciò che dovresti usare.
Giovanni 1024,

4

Non puoi annullare sourcela sceneggiatura.

Quello che puoi fare è archiviare tutte le variabili esportate in un file temporaneo, confrontarlo con le variabili dopo aver ottenuto lo script e quindi rimuovere l'overflow con unset, ad esempio:

export > temp_file
source myscript

#... do some stuff

unset "$(comm -3 <(sort temp_file) <(export | sort) | awk -F'[ =]' '{print $3}' | tr '\n' ' ')"

perché non usarlo - per i nel file `awk '{print $ 2}' | awk -F "=" '{print $ 1}' `; disinserire $ i; fatto ? (più semplice per non essere impostato)
yael

@yael funzionerà solo se lo script contiene solo exports.
jimmij,

cosa intendi con "export s", il mio file include linuxmachine01 = "sdb sdc sdf sdd sde sdg" e così via, e quando uso il ciclo awk disinserisce la variabile senza problemi
yael

@yael Non so come sia esattamente il tuo file, quindi ho dato una risposta generale, ad esempio se lo script contiene un commento in alto che dice "# Ecco alcune variabili da esportare con punti di montaggio".
Jimmij,

2

È possibile utilizzare il unsetcomando per "dimenticare" le variabili.


file potrebbe essere con macchine diff, quindi come disinserire le seconde variabili nel file?
yael

unset variablename lo dimenticherà (lo puoi trovare spiegato nella pagina man bash / sh / ksh / zsh) demo: pastebin.com/MGQyTZEA
francois P

sì, ma poiché le variabili potrebbero essere diff, lo script bash deve farlo leggendo la variabile dal file e disinserendole, non può essere statico perché la variabile è sconosciuta
yael

quindi grep le vostre linee di esportazione (tagliate) per elencare le variabili dal file da disinserire export linuxmachine06 = "sdb sde sdf sdd" quindi si ottiene linuxmachine06 come nome per annullare l'esempio: pastebin.com/M9eCtLc7 come si vede fare il comando unset qui conosci il nome della variabile che si conosce solo alla fine
francois P

ok userò questa sintassi per disinserire - per i nel file `awk '{print $ 2}' | awk -F "=" '{print $ 1}' `; disinserire $ i; fatto
yael

2

La soluzione più semplice per avere l'output che ti aspetti (niente) è di dichiarare nuovamente la variabile vuota:

$ export linuxmachine01="sdb sdc sdf sdd sde sdg"
$ echo "$linuxmachine01"
sdb sdc sdf sdd sde sdg

$ linuxmachine01=""
$ echo "$linuxmachine01"
$

Naturalmente la variabile è ancora definita (ed esportata), vuota ma definita:

$ declare -p linuxmachine01
declare -x linuxmachine01=""

Per rimuovere correttamente la variabile sia dall'ambiente che dalla shell in esecuzione, è necessario utilizzare unset (il modo consigliato):

$ unset linuxmachine01
$ declare -p linuxmachine01
bash: declare: linuxmachine01: not found
$ echo "$linuxmachine01"
$

1

Il modo più semplice per farlo è modificare lo script in modo che definisca anche un comando per annullare l'effetto dello script:

export linuxmachine01="sdb sdc sdf sdd sde sdg"
export linuxmachine02="sde sdd sdb sdf sdc"
export linuxmachine03="sdb sdd sdc sde sdf"
export linuxmachine06="sdb sde sdf sdd"
alias linuxmachines_mount_point='for v in linuxmachine01 linuxmachine02 linuxmachine03 linuxmachine04; do unset $v; done; unalias linuxmachines_mount_point'

Perché un alias anziché una funzione? Si noti che gli alias sono disabilitati nelle shell non interattive per impostazione predefinita, quindi pronti all'uso, questo non funzionerà in uno script.
Charles Duffy,

... in realtà, questo sarebbe ancora più semplice se avessimo definito solo una variabile, e quindi ne avessimo solo una da annullare :, declare -A linuxmachines=( [01]="sdb sdc sdf" [02]="sde sdd sdb" [03]="whatever" )quindi è solo unset linuxmachinesda ripristinare.
Charles Duffy,

@CharlesDuffy: sia alias che funzione vanno bene per questo scopo. Il motivo per cui non suggerisco di inserire tutto in una variabile è che la definizione di un comando di annullamento è molto più generica. È possibile annullare la definizione non solo di variabili ma anche di funzioni, alias, impostazioni di sistema, impostazioni del terminale, ecc. Fornisce un'astrazione migliore in quanto non è necessario preoccuparsi dell'esatto contenuto del comando annulla.
Lie Ryan

Credo che il mio punto sopra sia che gli alias non vanno bene per lo scopo, se "lo scopo" include un uso non interattivo (cioè invocazione da script).
Charles Duffy,

0

Puoi scrivere il tuo linuxmachines_mount_point.txt in questo modo

test "$linuxmachine01" && unset -v linuxmachine01 || linuxmachine01="sdb sdc sdf sdd sde sdg"

Quando hai bisogno delle tue variabili

source linuxmachines_mount_point.txt

Quando si desidera rimuovere le variabili

source linuxmachines_mount_point.txt

0

Se si utilizza il sourcecomando per attivare a VirtualEnvironment, è possibile uscire utilizzando il comando deactivate.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.