Exportieren einer Variable mit einem Punkt (.)

Exportieren einer Variable mit einem Punkt (.)

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 bashdie 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.homeda 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 rcShell und ihre Derivate mögen esund akangaunterstü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.yashzshbash

    $ 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önnen zshoder kshso 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).

  • ksh93hat 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 es zshProbleme mit seinen $pathoder $commandsspeziellen 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 ( bashentfernt die mit einem leeren Namen, ashund kshentfernt bashdie 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, cshund tcshunter 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 setBefehl gibt in Borne Shell jede Eigenschaft in einer separaten Zeile in der Form aus

C__any_value='my.property.key=the value'

Der awkBefehl 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 exportFunktionen mit Punktumgebungsnamen zu simulieren.

Um eine solche Variable zu „exportieren“, können Sie execdie aktuelle Shell mit enveinem Befehl aufrufen. Um test.env=fooeine 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"}'

verwandte Informationen