Kann der Name der Shell-Variablen einen Bindestrich oder Bindestrich (-) enthalten?


38

Ich kann keine -Variablen in der Shell verwenden. Gibt es eine Möglichkeit, es zu verwenden, da ich ein Skript habe, das von solchen benannten Variablen abhängt:

$export a-b=c
-bash: export: `a-b=c': not a valid identifier

$export a_b=c

Erstens wirft der angegebene Fehler und zweitens funktioniert gut.



In Shells sind solche Variablennamen normalerweise nicht zulässig. Sie müssten die Shell umgehen, möglicherweise sogar mit einem benutzerdefinierten C-Programm, das die Variablen in die Umgebung Ihres Befehls lädt. Können Sie diesen Fehler nicht beheben (sogar ein mögliches Sicherheitsrisiko)?
Vonbrand

Antworten:


47

Ich habe noch nie eine Bourne-artige Shell getroffen, die -einen Variablennamen zulässt. Es werden nur ASCII-Buchstaben (in beiden Fällen) _und Ziffern unterstützt, und das erste Zeichen darf keine Ziffer sein.

Wenn Sie ein Programm haben, für das eine Umgebungsvariable erforderlich ist, die nicht den Shell-Einschränkungen entspricht, starten Sie es mit dem envProgramm.

env 'strange-name=some value' myprogram

Beachten Sie, dass einige Shells (z. B. moderner Bindestrich , mksh, zsh) Variablen, deren Namen sie nicht mögen, aus der Umgebung entfernen. ( Shellshock hat dazu geführt, dass die Leute bei Umgebungsvariablennamen vorsichtiger sind. Daher werden die Einschränkungen mit der Zeit wahrscheinlich strenger und nicht zulässiger.) Wenn Sie also eine Variable übergeben müssen, deren Name Sonderzeichen enthält, übergeben Sie sie direkt an ein Programm. ohne eine Shell dazwischen ( env 'strange-name=some value' sh -c'…; myprogram'kann oder kann nicht funktionieren).


Funktioniert nicht mehr.
Jesse Glick

4
@ JesseGlick Ja, das tut es. (Ihr Kommentar wäre nützlich, wenn Sie „funktioniert nicht“ definiert hätten: Mit welchen Daten? Was ist der Effekt anstelle des gewünschten Effekts? Und wenn Sie sagten, welche Implementierung envSie auf welchem ​​Betriebssystem verwendet haben.)
Gilles 'SO - hör auf zu sein böse '

Es tut uns leid. Ubuntu Yakkety mit allen Updates, envvon coreutils, shvon dash: env 'with-dashes=value' bash -c 'env | fgrep dashes'funktioniert aber env 'with-dashes=value' sh -c 'env | fgrep dashes'druckt nichts. Das heißt, envselbst ist in Ordnung, aber Dash scheint diese Variablen spezifisch zu blockieren. Wenn also das betreffende Programm über einen Shell-Wrapper mit einem typischen #!/bin/shHeader gestartet wird , gibt es keine offensichtliche Möglichkeit, solche Variablen weiterzugeben. Beispiel Workaround
Jesse Glick

@JesseGlick Das ist ein Strich, der die Variable entfernt. Sie müssen envnäher an der aufrufenden Site des Programms, das diesen Variablennamen benötigt, eine Shell dazwischen verwenden. Dash ist nicht der Einzige, der Variablen entfernt, deren Name ihm nicht gefällt.
Gilles 'SO- hör auf böse zu sein'

1
@JesseGlick Es ist wahr, dass einige Dinge, die früher funktionierten, möglicherweise nicht mehr funktionieren: Seit Shellshock sind die Leute konservativer in Bezug auf Variablennamen geworden, und Dash hat sich tatsächlich geändert, seit ich diese Antwort geschrieben habe (allerdings nicht als Folge von Shellshock, aber um einen Fehler in die gleiche Richtung zu vermeiden). Ich habe meiner Antwort eine Notiz hinzugefügt.
Gilles 'SO- hör auf böse zu sein'

15

In Bash ist das nicht möglich.

Im Abschnitt " Definitionen " auf der Handbuchseite von bash:

name Ein Wort, das nur aus alphanumerischen Zeichen und Unterstrichen besteht und mit einem alphabetischen Zeichen oder einem Unterstrich beginnt. Wird auch als Kennung bezeichnet.

Aus dem Abschnitt Parameter in der Handbuchseite von bash:

Ein Parameter ist eine Entität, die Werte speichert. Dies kann ein Name, eine Nummer oder eines der Sonderzeichen sein, die unten unter "Sonderparameter" aufgeführt sind. Eine Variable ist ein Parameter, der mit einem Namen bezeichnet wird.


2
+1, um die Nützlichkeit von Manpages noch einmal zu demonstrieren
ktf 31.10.11

2
Alte Post kenne ich aber, ich möchte darauf hinweisen, dass für Newcomer Manpages durchaus kryptisch sein können. Ich habe immer noch Zeiten, in denen ich bessere Erklärungen / Beispiele suchen muss. Jeder würde lügen, wenn sie sagten, dass es ihnen nie passiert ist.
TCZ8

1
@ TCZ8 Die einzigen Leute, die mir erzählt haben, dass sie Manpages für "kryptisch" halten, sind die gleichen Leute, die keine Fehlermeldungen lesen und einfach alles überfliegen und direkt darüber hinweggehen, was sie lesen müssen.
Miles Rout

13

Sie können über eine indirekte Referenz auf eine mit Bindestrich versehene Variable zugreifen.

$ env 'my-hyphenated-variable=hello' /bin/bash
$ name='my-hyphenated-variable'
$ echo ${!name}
hello

1
Ich hatte bis zum Lesen dieses Kommentars noch nie von dieser Funktionalität gehört. Eine viel einfachere Lösung für mich als die akzeptierte Antwort.
DrStrangepork

7
Dieses Verhalten wurde in neueren Versionen von Bash deaktiviert. Eine gründliche Analyse der Situation finden Sie unter stackoverflow.com/questions/36989263/… .
Nicolas Dudebout

6

Wenn Ihr Skript davon abhängt, dass Variablennamen Bindestriche enthalten, liegt ein Programmierfehler vor. Wenn es für Sie aufgrund der Tools, die Sie regelmäßig verwenden, um die Variablennamen mit einem Bindestrich zu versehen, praktisch ist, müssen Sie möglicherweise mehr und andere Tools lernen.

Haben Sie versucht , die Bindestriche mit tr in Unterstriche umzuwandeln?

hyphenated_name="a-b"
unhyphenated_name=$(echo $hyphenated_name | tr '-' '_')
declare -x $unhyphenated_name="some value"

Bash erlaubt das Auftauchen von '-' in Funktionsnamen. Ich mache das die ganze Zeit. Beispielsweise:

function foo-bar() {
   echo "$@"
}

2

Das Bindestrich ( -) -Zeichen ist ein Umbruchzeichen und als Teil von Variablennamen nicht zulässig. Es gibt Möglichkeiten, dies mit zitierten Variablen zu hacken, aber das Parsen ist wirklich problematisch. Es gibt auch andere Zeichen mit besonderer Bedeutung im Zusammenhang mit Variablennamen in Bash, insbesondere geschweifte Klammern, Klammern, Operatorzeichen und Anführungszeichen. (zB {}()=+-&'"und mehr)

Ich würde vorschlagen, dass Sie praktisch ein anderes Paradigma finden müssen, auf dem Sie Ihr Skript aufbauen können. Möglicherweise haben Sie eine Ahnung von anderen Sprachen über "variable Variablennamen". In Shell-Skripten ist dies im Allgemeinen keine gute Idee.

Wenn Sie dies bearbeiten oder eine neue Frage mit Details zu Ihrem Kontext und dem, was Sie erreichen möchten, stellen, können wir möglicherweise eine gute Methode für die Skripterstellung vorschlagen.


2

Das Bash-Handbuch definiert einen "Namen" als:

Ein Wort, das ausschließlich aus Buchstaben, Zahlen und Unterstrichen besteht und mit einem Buchstaben oder Unterstrich beginnt. 'Namen werden als Shell-Variablen- und Funktionsnamen verwendet. Wird auch als "Kennung" bezeichnet.

Sie können also keinen Bindestrich in einem Namen verwenden.


0

Die meisten Shells unterstützen nur az, AZ, 0-9 und _ für Variablennamen. Lesen Sie den zweiten Punkt auf dieser Seite .


0

Sie können mit env und sed spielen.

Als Beispiel musste ich diese Variable 'ELASTICSEARCH_CLUSTER-NODES' lesen.
Der Befehl env gibt Folgendes aus:

~ $ env
ELASTICSEARCH_CLUSTER-NODES=elasticsearch:9200
JAVA_ALPINE_VERSION=8.212.04-r0
HOSTNAME=17eb9e7fec4c
...

So extrahieren Sie die Variable:

ESHOST=`env | sed -n 's/ELASTICSEARCH_CLUSTER-NODES=\(.*\)/\1/p'`

-1

Ich glaube, dass nur Buchstaben, Zahlen und Unterstriche für Bash-Variablen zulässig sind. Dies ist in vielen Programmiersprachen der Fall (Javascript ist eine Ausnahme).

Ich empfehle, Ihr Skript nicht von solchen Variablennamen abhängig zu machen.

In der Tat sollten Sie versuchen, so zu programmieren, dass Sie Variablennamen durch andere Namen ersetzen können, und es macht keinen Unterschied. Im Allgemeinen sollten Variablennamen beschreiben, was die Variable enthält. Dies erleichtert das Debuggen erheblich. Wenn nicht für Sie, dann für den nächsten Entwickler, der versucht, den Code herauszufinden.


-1

Mit dem envBefehl können Sie Umgebungsvariablen mit den Zeichen "-" setzen und entfernen.

So legen Sie müssen Ihren Befehl env auszuführen: env command. Sie übergeben Variablen folgendermaßen:

env a-b=c command

Sehen Sie, wie es funktioniert mit:

env a-b=c env

oder um es klarer zu machen:

env a-b=c env|grep 'a-b'
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.