Gegenüber dem Befehl `source`


9

Ich benutze den sourceBefehl in meinem Bash-Skript, um die Variablenwerte zu lesen / drucken

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

Was ist das Gegenteil von, sourceum die Variablen zu deaktivieren?

Erwartete Ergebnisse

echo $linuxmachine01

< no output >

14
Es ist nicht sourcedas Festlegen der Variablen in Ihrer Umgebung, sondern die exportAnweisungen in der Datei, die Sie source. Das Gegenteil von sourcekönnte also sein source, wenn Sie sourceeine andere Datei haben, die unsetalle die gleichen Variablen enthält.
user4556274

2
yael, benutze keine Exporte, benutze einfach name = "val". Der Export erfolgt für Skript-zu-Binär-Variablen (die Umgebung).
Strg-D


2
Das ist unmöglich. Das Konzept, das Sie suchen, heißt Reversible Computing . Programmiersprachen müssen speziell mit einigen schwerwiegenden Einschränkungen entworfen werden, um reversibel zu sein. Bash ist keine dieser Programmiersprachen.
Jörg W Mittag

1
@yael, das ist nicht wahr (und du hast offensichtlich nie den Test ausgeführt, den du mit Strg-D befohlen hast); du brauchst das exports absolut nicht . Alles, exportwas Sie tun müssen, ist, die Werte in die Umgebung zu kopieren. Sie sind jedoch als Shell-Variablen vorhanden, unabhängig davon, ob sie auch als Umgebungsvariablen definiert sind oder nicht. Darüber hinaus verkürzt das Definieren unnötiger Umgebungsvariablen Ihre maximale Befehlszeilenlänge, da sie im selben (begrenzten!) Pro-Prozess-Bereich gespeichert werden.
Charles Duffy

Antworten:


21

Verwenden einer Unterschale (empfohlen)

Führen Sie den Quellbefehl in einer Subshell aus:

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

Unterschalen werden durch Parens definiert : (...). Alle innerhalb der Subshell festgelegten Shell-Variablen werden beim Ende der Subshell vergessen.

Verwenden von unset

Dadurch werden alle Variablen deaktiviert, die exportiert werden von linuxmachines_mount_point.txt:

unset $(awk -F'[ =]+' '/^export/{print $2}' linuxmachines_mount_point.txt)
  • -F'[ =]+' Weist awk an, eine beliebige Kombination von Leerzeichen und Gleichheitszeichen als Feldtrennzeichen zu verwenden.

  • /^export/{print $2}

    Dies weist awk an, Zeilen auszuwählen, die mit beginnen, exportund dann das zweite Feld zu drucken.

  • unset $(...)

    Dadurch wird der Befehl ausgeführt $(...), das Standardout erfasst und alle durch die Ausgabe benannten Variablen deaktiviert.


warum nicht verwenden - für i in `awk '{print $ 2}' Datei | awk -F "=" '{print $ 1}' `; deaktiviere $ i; getan ? (einfacher für nicht gesetzt)
Yael

2
@yael Das verwendet einen zusätzlichen Prozess und eine Schleife, wenn keine benötigt werden. Die Meinungen mögen variieren, aber ich sehe das nicht als einfacher an. Außerdem und potenziell gefährlich wird davon ausgegangen, dass jede Zeile fileeine Exportanweisung ist.
John1024

8
@yael Auch das Deaktivieren von Variablen und das Rückgängigmachen anderer Code-Nebenwirkungen ist genau das, wofür Subshells gedacht sind. Sie machen es einfach und zuverlässig. Sofern es keinen besonderen Grund gibt, sollten Sie Unterschalen verwenden.
John1024

4

Sie können sourcedas Skript nicht aufheben .

Was Sie tun können, ist, alle exportierten Variablen in einer temporären Datei zu speichern, sie mit Variablen zu vergleichen, nachdem das Skript bezogen wurde, und dann den Überlauf zu entfernen unset, z.

export > temp_file
source myscript

#... do some stuff

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

warum nicht verwenden - für i in `awk '{print $ 2}' Datei | awk -F "=" '{print $ 1}' `; deaktiviere $ i; getan ? (einfacher für nicht gesetzt)
Yael

@yael es wird nur funktionieren, wenn das Skript nur exports enthält .
Jimmyij

Was du meinst "export s", meine Datei enthält linuxmachine01 = "sdb sdc sdf sdd sde sdg" und so weiter, und wenn ich die awk-Schleife benutze, wird die Variable ohne Probleme
deaktiviert

@yael Ich weiß nicht, wie genau Ihre Datei aussieht, daher habe ich eine allgemeine Antwort gegeben, zum Beispiel, wenn das Skript oben einen Kommentar mit der Aufschrift "# Hier sind einige Variablen, die mit Einhängepunkten exportiert werden sollen" enthält.
Jimmyij

2

Sie können den unsetBefehl verwenden, um Variablen zu "vergessen".


Datei könnte mit Diff-Maschinen sein, wie kann man also die zweiten Variablen in der Datei deaktivieren?
Yael

Der nicht festgelegte Variablenname wird es vergessen (Sie finden ihn in der Manpage bash / sh / ksh / zsh erklärt). Demo: pastebin.com/MGQyTZEA
francois P

Ja, aber da Variablen unterschiedlich sein können, muss das Bash-Skript dies tun, indem es die Variable aus der Datei liest und sie
deaktiviert.

Dann grep deine Exportzeilen (Ausschneiden), um Variablen aus der zu deaktivierenden Datei aufzulisten. export linuxmachine06 = "sdb sde sdf sdd". Dann erhältst du linuxmachine06 als Namen zum Deaktivieren. Beispiel: pastebin.com/M9eCtLc7, wie du den Befehl unset hier siehst
Francois P

ok Ich werde diese Syntax verwenden, um zu deaktivieren - für i in `awk '{print $ 2}' Datei | awk -F "=" '{print $ 1}' `; deaktiviere $ i; fertig
Yael

2

Die einfachste Lösung für die erwartete Ausgabe (nichts) besteht darin, die Variable erneut als leer zu deklarieren:

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

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

Natürlich ist die Variable immer noch definiert (und exportiert), leer, aber definiert:

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

Um die Variable sowohl aus der Umgebung als auch aus der laufenden Shell korrekt zu entfernen, sollten Sie unset verwenden (die empfohlene Methode):

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

1

Der einfachste Weg, dies zu tun, besteht darin, Ihr Skript so zu ändern, dass es auch einen Befehl definiert, um die Wirkung des Skripts rückgängig zu machen:

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'

Warum eher ein Alias ​​als eine Funktion? Beachten Sie, dass Aliase in nicht interaktiven Shells standardmäßig deaktiviert sind. Daher funktioniert dies in einem Skript nicht sofort.
Charles Duffy

... eigentlich wäre dies sogar noch einfacher, wenn wir nur eine Variable definieren würden und daher nur eine zu deaktivieren hätten: declare -A linuxmachines=( [01]="sdb sdc sdf" [02]="sde sdd sdb" [03]="whatever" )Dann ist es nur unset linuxmachineszum Zurücksetzen.
Charles Duffy

@CharlesDuffy: Sowohl Alias ​​als auch Funktion sind für diesen Zweck in Ordnung. Der Grund, warum ich nicht vorschlage, alles in eine Variable zu setzen, ist, dass das Definieren eines Rückgängig-Befehls viel allgemeiner ist. Sie können nicht nur Variablen, sondern auch Funktionen, Aliase, Systemeinstellungen, Terminaleinstellungen usw. undefinieren. Dies bietet eine bessere Abstraktion, da Sie sich nicht um den genauen Inhalt des Rückgängig-Befehls kümmern müssen.
Lie Ryan

Ich glaube, mein Punkt oben ist, dass Aliase für den Zweck nicht in Ordnung sind , wenn "der Zweck" eine nicht interaktive Verwendung umfasst (dh Aufruf von Skripten).
Charles Duffy

0

Sie können Ihre linuxmachines_mount_point.txt so schreiben

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

Wenn Sie Ihre Variablen benötigen

source linuxmachines_mount_point.txt

Wenn Sie die Variablen entfernen möchten

source linuxmachines_mount_point.txt

0

Wenn Sie den sourceBefehl zum Aktivieren von a verwenden VirtualEnvironment, können Sie ihn mit dem Befehl beenden deactivate.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.