Il nome della variabile shell può includere un trattino o un trattino (-)?


38

Non sono in grado di utilizzare le -variabili nella shell. C'è un modo per poterlo usare, perché ho uno script che dipende da tali variabili denominate:

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

$export a_b=c

Innanzitutto genera l'errore indicato e il secondo funziona correttamente.



Le conchiglie di solito non consentono tali nomi di variabili. Dovresti bypassare la shell, forse anche con un programma C personalizzato che carica le variabili nell'ambiente del tuo comando. Non riesci a correggere questo malfunzionamento (anche possibile rischio di sicurezza)?
vonbrand,

Risposte:


47

Non ho mai incontrato una shell in stile Bourne che mi permettesse -di usare un nome variabile. Sono _supportate solo lettere ASCII (di entrambi i casi) e cifre, e il primo carattere non deve essere una cifra.

Se si dispone di un programma che richiede una variabile di ambiente che non corrisponde alle restrizioni della shell, avviarlo con il envprogramma.

env 'strange-name=some value' myprogram

Si noti che alcune shell (ad esempio trattino moderno , mksh, zsh) rimuovono le variabili il cui nome non piace all'ambiente. ( Shellshock ha reso le persone più caute sui nomi delle variabili di ambiente, quindi è probabile che le restrizioni diventino più rigorose nel tempo, non più permissive.) Quindi, se è necessario passare una variabile il cui nome contiene un carattere speciale a un programma, passarlo direttamente, senza una shell in mezzo ( env 'strange-name=some value' sh -c'…; myprogram'può o non può funzionare).


Non lavora più.
Jesse Glick,

4
@JesseGlick Sì. (Il tuo commento sarebbe utile se definissi "non funzionante": con quali dati? Qual è l'effetto invece dell'effetto desiderato? E se dicessi quale implementazione envhai utilizzato su quale sistema operativo.)
SO di Gilles smetti di essere male '

Scusate. Ubuntu Yakkety con tutti gli aggiornamenti, envda coreutils, shda dash: env 'with-dashes=value' bash -c 'env | fgrep dashes'funziona ma env 'with-dashes=value' sh -c 'env | fgrep dashes'non stampa nulla. Cioè, di per envsé va bene, ma Dash sembra bloccare specificamente queste variabili. Pertanto, se il programma in questione viene avviato tramite un wrapper di shell con #!/bin/shun'intestazione tipica , non esiste un modo apparente per passare tali variabili. soluzione alternativa di esempio
Jesse Glick

@JesseGlick Questo è il trattino che rimuove la variabile. Devi usare envpiù vicino al sito chiamante del programma che necessita di questo nome di variabile, senza una shell in mezzo. Dash non è il solo a rimuovere le variabili il cui nome non gli piace.
Gilles 'SO- smetti di essere malvagio' il

1
@JesseGlick È vero che alcune cose che un tempo funzionavano potrebbero non funzionare più: dal momento che lo shellshock , le persone sono diventate più prudenti riguardo ai nomi delle variabili e il trattino è effettivamente cambiato da quando ho scritto questa risposta (non come conseguenza di Shellshock, ma per evitare un bug sulla stessa linea). Ho aggiunto una nota alla mia risposta.
Gilles 'SO- smetti di essere malvagio' il

15

Questo non è possibile in Bash.

Dalla sezione Definizioni nella pagina del manuale di bash:

nome Una parola composta solo da caratteri alfanumerici e caratteri di sottolineatura e che inizia con un carattere alfabetico o un trattino basso. Indicato anche come identificatore.

Dalla sezione Parametri nella pagina del manuale di bash:

Un parametro è un'entità che memorizza valori. Può essere un nome, un numero o uno dei caratteri speciali elencati di seguito in Parametri speciali. Una variabile è un parametro indicato da un nome.


2
+1 per dimostrare ancora una volta l'utilità delle pagine man
ktf

2
Vecchio post lo so ma, voglio sottolineare che per i neofiti le pagine man possono essere piuttosto enigmatiche. Ho ancora dei momenti in cui ho bisogno di cercare spiegazioni / esempi migliori. Tutti mentirebbero se dicessero che non è mai successo a loro.
TCZ8,

1
@ TCZ8 Le uniche persone che mi hanno detto di pensare che le pagine man fossero "criptiche" sono lo stesso tipo di persone che non leggono i messaggi di errore e si limitano a leggere tutto, saltando proprio quello che devono leggere.
Miles Rout,

13

È possibile accedere a una variabile sillabata utilizzando un riferimento indiretto.

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

1
Non avevo mai sentito parlare di questa funzionalità fino a quando non ho letto questo commento. Mi ha fornito una soluzione molto più semplice della risposta accettata.
DrStrangepork,

7
Questo comportamento è stato disabilitato nelle versioni più recenti di bash. Consulta stackoverflow.com/questions/36989263/… per un'analisi approfondita della situazione.
Nicolas Dudebout,

6

Se la tua sceneggiatura dipende dal fatto che i nomi delle variabili abbiano trattini, si tratta di un errore di programmazione. Se è conveniente per te a causa degli strumenti che usi regolarmente per avere i nomi delle variabili contenenti un trattino, potresti dover imparare di più e strumenti diversi.

Hai provato a usare tr per convertire i trattini in caratteri di sottolineatura?

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

Bash consente a "-" di apparire nei nomi delle funzioni. Lo faccio sempre. Per esempio:

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

2

Il trattino (- ) è un carattere di interruzione e non consentito come parte dei nomi delle variabili. Ci sono modi per hackerare questo con variabili tra virgolette, ma l'analisi è davvero problematica. Ci sono anche altri personaggi con significati speciali nel contesto di nomi di variabili in bash, in particolare parentesi graffe, parentesi, caratteri operatore e virgolette. (ad es. {}()=+-&'"e altro)

Suggerirei che praticamente devi trovare un altro paradigma su cui costruire la tua sceneggiatura. Potresti avere un'idea da altre lingue sui "nomi delle variabili variabili". Questa non è generalmente una buona idea negli script di shell.

Se lo modifichi o fai una nuova domanda con i dettagli del tuo contesto e cosa stai cercando di realizzare, potremmo essere in grado di suggerire un buon modo per copiarlo.


2

Il manuale di Bash definisce un "nome" come:

Una "parola" costituita esclusivamente da lettere, numeri e caratteri di sottolineatura e che inizia con una lettera o un trattino basso. 'I nomi sono usati come variabili di shell e nomi di funzioni. Chiamato anche "identificatore".

Quindi non puoi usare un trattino in un nome.


0

La maggior parte delle shell supporta solo az, AZ, 0-9 e _ per i nomi di variabili. Leggi il secondo elemento in questa pagina .


0

Puoi giocare con env e sed.

Ad esempio, dovevo leggere questa variabile "ELASTICSEARCH_CLUSTER-NODES".
Il comando env ha prodotto questo:

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

Quindi per estrarre la variabile:

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

-1

Credo che solo le lettere, i numeri e il carattere di sottolineatura siano consentiti per le variabili bash. Questo è il caso in molti linguaggi di programmazione (javascript è un'eccezione).

Consiglio di non far dipendere il tuo script da questi tipi di nomi di variabili.

In effetti, dovresti provare a programmare in modo tale da poter sostituire i nomi delle variabili con altri nomi e non fa differenza. In generale, i nomi delle variabili dovrebbero descrivere ciò che contiene la variabile. Questo rende molto più facile il debug; se non per te, quindi per il prossimo sviluppatore che sta cercando di capire il codice.


-1

È possibile utilizzare il envcomando per impostare e annullare l'impostazione delle variabili di ambiente con hiphens "-".

Per impostare è necessario utilizzare ENV per eseguire il comando: env command. Si passano le variabili in questo modo:

env a-b=c command

Guardalo lavorare con:

env a-b=c env

o per chiarire:

env a-b=c env|grep 'a-b'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.