Importieren von Variablen in ein Shell-Skript aus einem anderen, ohne das referenzierte Shell-Skript auszuführen

Importieren von Variablen in ein Shell-Skript aus einem anderen, ohne das referenzierte Shell-Skript auszuführen

Ich habe 2 Shell-Skripte, file1.sh und file2.sh

datei1.sh

#!/usr/bin/env bash 
export var1="/data/share"
export var2='password'
echo "Hello"

file2.sh

#!/usr/bin/env bash 
source file1.sh
echo $var1
echo $var2

Wenn ich file2.sh ausführe, erhalte ich die folgende Ausgabe

Hello
/data/share
password

Aber mein erwartetes Ergebnis ist

/data/share
password

file1.sh wird ausgeführt, wenn in file2.sh darauf verwiesen wird. Wie importiere ich die Variablen allein in file2.sh, ohne file1.sh auszuführen?

Antwort1

Es gibt drei Optionen, die ich verwende, wenn ich ein Bash-Skript habe, das sich beim Aufrufen anders verhalten soll als beim Ausführen (oder mit anderen Worten, wenn ich Datenelemente in einem Skript habe, auf die ich zugreifen möchte, ohne zu diesem Zeitpunkt Code auszuführen). Die Kommentare haben diese bis zu einem gewissen Grad angesprochen.

Option eins

Bestimmen Sie, wann beschafft wird, und beenden Sie die Beschaffung zum geeigneten Zeitpunkt

Teilen Sie das Skript in zwei Abschnitte auf und beenden Sie es, wenn die Quelle angegeben wird, bevor Sie zur unteren zweiten Zeile gelangen.

Erstellen Sie einen oberen Skriptabschnitt mit Definitionen (Funktionen/Variablenzuweisungen usw.), aber ohne direkte Codeausführung.

Direkt vor dem Beginn des ausführbaren Codeabschnitts platzieren Sie eine Logik, die das Skript beendet, wenn es erkennt, dass es als Quelle verwendet wird. Das folgende Codesegment tut dies:


datei1.sh

#!/usr/bin/env bash
export var1="/data/share"
export var2='password'    
# --- End Definitions Section ---    
# check if we are being sourced by another script or shell
[[ "${#BASH_SOURCE[@]}" -gt "1" ]] && { return 0; }
# --- Begin Code Execution Section ---
echo "Hello"
echo $var1
echo $var2 


file2.sh

#!/usr/bin/env bash 
source file1.sh
echo "$var1"
echo "$var2"


Ausgabe der Ausführung von ./file2.sh

$ ./file2.sh 
/data/share
password

Option Zwei

Dieser Modus wird normalerweise nur in komplexen Situationen verwendet und ist für dieses spezielle Beispiel übertrieben. Ich erstelle eine Funktion in der Datei, die ich als Quelle verwenden möchte, und bestimme in dieser Funktion, was dem Anrufer zur Verfügung stehen soll. In diesem Fall sind es die beiden exportierten Variablen. Normalerweise verwende ich diesen Modus, wenn ich assoziative Arrays habe, die sonst kaum zu übergeben sind. Außerdem sollte die temporäre Datei vom Anrufer gelöscht werden; in diesem Fall habe ich das jedoch nicht getan:


datei1.sh

#!/usr/bin/env bash 
export var1="/data/share"
export var2='password'
exportCfg() {
  tmpF=$(mktemp)
  declare -p var1 var2 > "$tmpF"
  echo "$tmpF"
}
if [ "$1" == "export" ]; then
  exportCfg;
  exit 0;
fi

echo "Hello"
echo $var1
echo $var2


file2.sh

#!/usr/bin/env bash 
source $(./file1.sh export)


echo "$var1"
echo "$var2"

Die Ausgabe der Ausführung von file2.sh ist die gleiche wie oben

Option 3

Die letzte übliche Methode, mit der ich das handhabe, ist einfach eine Bibliotheksdatei, die nur Definitionen enthält und keinen Code hat, der ausgeführt wird, wenn er bezogen oder direkt ausgeführt wird. Dabei geht es einfach darum, Ihren Code aufzuteilen. Ich habe eine Gruppe von Bash-Bibliotheken, die häufig verwendete Funktionen enthalten, und richte normalerweise pro Projekt eine kleine ausführbare Bibliothek zum Speichern von Konfigurationsdaten (Konstanten) ein. Wenn diese Daten ausgefüllte Arrays enthalten, verwende ich auch eine Version von Option 2.

Antwort2

Wenn Ihre Variablen alle auf die gleiche Weise exportiert werden (exportiere foo=bar), dann können Sie sie alle ganz einfach beziehen mitSchlagProzesssubstitutionsfunktion:

source <(grep '^export .*=' file1.sh)

Auszug aus der Manpage:

Prozessersetzung Prozessersetzung wird auf Systemen unterstützt, die benannte Pipes (FIFOs) oder die /dev/fd-Methode zum Benennen offener Dateien unterstützen. Sie hat die Form <(Liste) oder >(Liste). Der Prozess Liste wird mit seiner Eingabe oder Ausgabe ausgeführt, die mit einer FIFO oder einer Datei in /dev/fd verbunden ist. Der Name dieser Datei wird als Ergebnis der Erweiterung als Argument an den aktuellen Befehl übergeben. Wenn die Form >(Liste) verwendet wird, liefert das Schreiben in die Datei eine Eingabe für die Liste. Wenn die Form <(Liste) verwendet wird, sollte die als Argument übergebene Datei gelesen werden, um die Ausgabe der Liste zu erhalten.

verwandte Informationen