So exportieren Sie eine Variable, die einen Punkt enthält. Ich erhalte die Meldung „ungültiger Variablenname“, wenn ich Folgendes versuche:
export my.home=/tmp/someDir
-ksh: my.home=/tmp/someDir: invalid variable name
Auch das Escapen des Metazeichens Punkt (.) hat nicht geholfen
$ export my\.home=/tmp/someDir
export: my.home=/tmp/someDir: is not an identifier
Antwort1
Zumindest bash
die Manpage definiert die Exportsyntax wie folgt:
export [-fn] [name[=word]] ...
Außerdem wird ein „Name“ wie folgt definiert:
name A word consisting only of alphanumeric characters and under‐
scores, and beginning with an alphabetic character or an under‐
score. Also referred to as an identifier.
Sie können eine Variable daher nicht wirklich so definieren, my.home
da es sich nicht um einen gültigen Bezeichner handelt.
Ich bin mir sehr sicher, dass Ihr KSH eine sehr ähnliche Definition eines Bezeichners hat und daher diese Art von Variablen ebenfalls nicht zulässt. (Sehen Sie sich die Manpage dazu an.)
Ich bin mir auch sehr sicher, dass es eine Art allgemeinen Standard (POSIX?) gibt, der festlegt, was als Bezeichner (und daher als Variablenname) zulässig ist.
Wenn Sie diese Art von Variable aus irgendeinem Grund wirklich benötigen, können Sie etwas wie verwenden
env "my.home=/tmp/someDir" bash
um es trotzdem zu definieren. Aber dann können Sie mit der normalen Shell-Syntax nicht darauf zugreifen. In diesem Fall benötigen Sie wahrscheinlich eine andere Sprache wie Perl:
perl -e 'print $ENV{"my.home"}'
Zum Beispiel
env "my.home=/tmp/someDir" perl -le 'print $ENV{"my.home"}'
sollte Ihren Pfad drucken.
Antwort2
Während Umgebungsvariablen beliebige Namen haben können (einschließlich der leeren Zeichenfolge), die kein Gleichheitszeichen oder Nullbyte enthält, ordnen Shells Umgebungsvariablen Shellvariablen zu, und in den meisten Shells sind Variablennamen auf alphanumerische ASCII-Zeichen beschränkt, _
wobei das erste Zeichen keine Ziffer sein darf (mit Ausnahme der Positionsparameter und anderer spezieller Parameter wie $*
, $-
, $@
, …, (die nicht den entsprechenden Umgebungsvariablen zugeordnet sind)). Beachten Sie auch, dass einige Variablenreserviert/speziellvon/zur Shell.
Ausnahmen hiervon:
Die
rc
Shell und ihre Derivate mögenes
undakanga
unterstützen alle Namen außer leeren Zeichenfolgen und solche, die rein numerisch sind oder=
Zeichen enthalten (und exportieren immer alle ihre Variablen in die Umgebung und seien Sie vorsichtig bei speziellen Variablen wie*
,status
,pid
...):; '%$£"' = test ; echo $'%$£"' test ; '' = x zero-length variable name ;
Es verwendet jedoch eine eigene Kodierung für Variablen, deren Namen keine Alnums enthalten, oder für Arrays, wenn sie in der Umgebung der ausgeführten Befehle übergeben werden:
$ rc -c '+ = zzz; __ = zzz; a = (zzz xxx); env' | sed -n /zzz/l __2b=zzz$ __5f_=zzz$ a=zzz\001xxx$ $ env +=x rc -c "echo $'+'" x $ env __2b=x rc -c "echo $'+'" x
AT&T und (auch
ksh
, aber nur für Einzelbyte-Zeichen) unterstützen Alnums im aktuellen Gebietsschema, nicht nur ASCII-Alnums.yash
zsh
bash
$ Stéphane=1 $ echo "$Stéphane" 1
In diesen Shells können Sie das Gebietsschema so ändern, dass die meisten Zeichen als Alphazeichen betrachtet werden, aber das würde trotzdem nicht für ASCII-Zeichen wie funktionieren
.
. Sie könnenzsh
oderksh
so täuschen, dass£
es sich um einen Buchstaben handelt, aber nicht um diesen.
oder ein anderes ASCII-Zeichen (was das Zulassen von Zeichen in Variablennamen betrifft,[[:alpha:]]
beispielsweise nicht für den Glob).ksh93
hat spezielle Variablen, deren Name einen Punkt enthält, wie${.sh.version}
, aber diese sind nicht Umgebungsvariablen zugeordnet und sind speziell. Dies.
dient dazu, sicherzustellen, dass es nicht mit anderen Variablen in Konflikt gerät. Wenn es sich dafür entschieden hätte, es aufzurufen$sh_version
, hätte es möglicherweise Skripte beschädigt, die diese Variable bereits verwendet haben (siehe beispielsweise, wie eszsh
Probleme mit seinen$path
oder$commands
speziellen Array-/Hash-Variablen (a la csh) gibt, die einige Skripte beschädigen).
Beachten Sie, dass neben Shells, die diese Variablen nicht unterstützen, auch einige Shells wie pdksh/mksh diese unterstützen.entfernensie aus der Umgebung, die sie erhalten ( bash
entfernt die mit einem leeren Namen, ash
und ksh
entfernt bash
die Umgebungszeichenfolgen, die kein =
Zeichen enthalten):
$ env %%%=test 1=%%% a.b=%%% mksh -c env | grep %%%
$ env %%%=test 1=%%% a.b=%%% bash -c env | grep %%%
%%%=test
a.b=%%%
1=%%%
$ perl -le '$ENV{""}="%%%"; exec "bash", "-c", "env"' | grep %%%
$ perl -le '$ENV{""}="%%%"; exec "zsh", "-c", "env"' | grep %%%
=%%%
$ echo 'main(){char*a[]={"sh","-c","env",0};char*e[]={"%%%",0};
execve("/bin/ash",a,e);}'|tcc -run - | grep %%%
$ echo 'main(){char*a[]={"sh","-c","env",0};char*e[]={"%%%",0};
execve("/bin/zsh",a,e);}'|tcc -run - | grep %%%
%%%
Zusammenfassend lässt sich sagen, dass es am besten ist, bei den Variablennamen zu bleiben, die von den meisten Shells unterstützt werden, und sogar zu versuchen, Großbuchstaben für Umgebungsvariablen zu verwenden (und Kleinbuchstaben oder eine gemischte Schreibweise für nicht exportierte Shell-Variablen) und diejenigen zu vermeiden, die in Shells eine Besonderheit darstellen (wie IFS
, PS1
, BASH_VERSION
…).
Wenn Sie eine solche Variable in einer Shell festlegen müssen, die sie nicht unterstützt, sie aber nicht verwirft, können Sie sie selbst erneut ausführen, beispielsweise mit:
#! /bin/ksh -
perl -e 'exit 1 unless defined($ENV{"a.b"})' || exec env a.b=%%% "$0" "$@"
(natürlich hilft das nicht, wenn Sie es mitten im Skript tun müssen, aber Sie könnten dann einen Blick aufdieser Ansatzum die Shell-Ausführungsumgebung über eine erneute Ausführung zu speichern und wiederherzustellen). Oder versuchen Sie den Debugger-Ansatz:
gdb --batch-silent -ex 'call putenv("a.b=%%%")' --pid="$$"
(das scheint mit zsh
, yash
, csh
und tcsh
unter Linux amd64 zu funktionieren, aber nicht mit einer der anderen Shells, die ich ausprobiert habe ( mksh
, ksh93
, bash
, dash
)).
Antwort3
Wie in den anderen Beiträgen erwähnt, erlauben die gängigsten Shells nicht das Setzen von Umgebungsvariablen mit Punkten im Namen. Ich habe jedoch Situationen gefunden, insbesondere bei Docker und aufgerufenen Programmen, in denen die Software Schlüsselwerte mit Punkten erforderte.
In jeder dieser Situationen könnten diese Schlüssel-Wert-Paare jedoch auch auf andere Weise als nur über Umgebungsvariablen an das Programm übergeben werden. In Ant können Sie beispielsweise „-propertyfile (Dateiname)“ verwenden, um eine als Eigenschaftsdatei formatierte Sammlung von Schlüssel-Werten zu übergeben. Confd ermöglicht „-backend file -file (YAML-Datei)“.
Ich habe die Umgebungsvariablen in der Form "C__any_value='my.property.key=der Wert'" übergeben. Anschließend habe ich den Programmaufruf so umgestellt, dass zuerst die Datei generiert wird:
set | awk -- 'BEGIN { FS="'\''" } /^C__/ {print $2}' > my-key-values.txt
Der set
Befehl gibt in Borne Shell jede Eigenschaft in einer separaten Zeile in der Form aus
C__any_value='my.property.key=the value'
Der awk
Befehl verarbeitet nur die Umgebungsvariablen, die mit beginnen C__
, und extrahiert dann die in den einfachen Anführungszeichen enthaltenen Werte.
Bei dieser Methode muss der Wert der Umgebungsvariablen genau in der Form festgelegt werden, die das Verarbeitungsprogramm benötigt. Wenn Ihr Eigenschaftswert oder Schlüssel außerdem einfache Anführungszeichen enthält, müssen Sie das awk-Feldtrennzeichen in ein Zeichen ändern, von dem Sie wissen, dass es nicht angezeigt wird, und den Wert mit diesem Zeichen umgeben. %
Als Trennzeichen verwenden Sie beispielsweise:
$ C__1="%my.key=the'value%"
$ set | awk -- 'BEGIN { FS="%" } /^C__/ {print $2}'
my.key=the'"'"'value
(Die genaue Ausgabe hängt von Ihrer Shell ab.) Sie müssen zusätzliche Schritte unternehmen, um die Anführungszeichen zu dekodieren.
Antwort4
Die Antwort von @michas ist völlig korrekt, aber es ist möglich, sie zu erweitern, um export
Funktionen mit Punktumgebungsnamen zu simulieren.
Um eine solche Variable zu „exportieren“, können Sie exec
die aktuelle Shell mit env
einem Befehl aufrufen. Um test.env=foo
eine Variable zu exportieren, verwenden Sie beispielsweise:
exec env "test.env=foo" $SHELL
Exec ersetzt die aktuelle Shell durch einen neuen Prozess, wobei der neue Prozess eine neue Instanz der aktuellen Shell ( $SHELL
) mit zusätzlicher Umgebungsvariable test.env
(hinzugefügt durch env "test.env=foo"
) ist. Nach diesem Befehl können Sie also von Ihrem Prozess aus darauf zugreifen, z. B.:
perl -e 'print $ENV{"test.env"}'