Exporter une variable contenant un point (.)

39

Comment exporter une variable qui contient un point. Je reçois le 'nom de variable invalide' quand j'ai essayé:

 export my.home=/tmp/someDir
-ksh: my.home=/tmp/someDir: invalid variable name

Même échapper à métacaractère dot (.) Din n'a pas aidé non plus

$ export my\.home=/tmp/someDir
export: my.home=/tmp/someDir: is not an identifier
utilisateur1587504
la source
1
malheureusement, il ne figurait pas dans la liste lorsque je tapais / cherchais une question similaire. Désolé. ..
user1587504

Réponses:

50

Au moins pour bashla page de manuel, la syntaxe d'exportation est définie comme suit:

export [-fn] [name[=word]] ...

Il définit également un "nom" comme:

   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.

Par conséquent, vous ne pouvez vraiment pas définir une variable comme my.homes'il ne s'agissait pas d'un identifiant valide.

Je suis très sûr que votre ksh a une définition très similaire d'un identifiant et n'autorise donc pas ce type de variables. (Consultez sa page de manuel.)

Je suis également très sûr qu'il existe une sorte de norme générale (POSIX?) Spécifiant ce qui est autorisé comme identifiant (et donc comme nom de variable).


Si vous avez vraiment besoin de ce type de variable pour une raison quelconque, vous pouvez utiliser quelque chose comme:

env "my.home=/tmp/someDir" bash

de le définir quand même. Mais là encore, vous ne pourrez pas y accéder avec la syntaxe de shell normale. Dans ce cas, vous avez probablement besoin d'une autre langue comme perl:

perl -e 'print $ENV{"my.home"}'

Par exemple

env "my.home=/tmp/someDir" perl -le 'print $ENV{"my.home"}'

devrait imprimer votre chemin.

michas
la source
C'est à cause de l'intégration de ant. Et malheureusement, cela ne permet pas de définir / exporter une variable à partir d’unix. Accepter votre réponse ..
user1587504
1
ant est généralement configuré par une seule variable d'environnement appelée ANT_OPTSou par ~ / .antrc. Pas besoin de noms de variables d'environnement étranges pour ant lui-même.
Michas
8

Alors que les variables d'environnement peuvent avoir n'importe quel nom (y compris la chaîne vide) ne contenant ni signe égal ni octet nul, les shells mappent les variables d'environnement à des variables shell et, dans la plupart des shells, les noms de variables sont limités aux caractères alphanumériques ASCII _. t un chiffre (sauf pour les paramètres de position et d' autres comme ceux spéciaux $*, $-, $@, ..., (qui ne sont pas mis en correspondance avec les variables d'environnement correspondantes)). Notez également que certaines variables sont réservées / spéciales par / au shell.

Les exceptions à cela:

  • La rccoquille et ses dérivés comme eset akangaprennent en charge un nom , sauf la chaîne vide, et ceux qui sont tout numérique ou contiennent des =caractères (et toujours exporter toutes leurs variables à l'environnement, et méfiez - vous des variables spéciales comme *, status, pid...):

    ; '%$£"' = test
    ; echo $'%$£"'
    test
    ; '' = x
    zero-length variable name
    ;
    

    Cependant, il utilise son propre codage pour les variables dont le nom ne contient pas d'alnums ou pour les tableaux lorsqu'il est passé dans l'environnement des commandes en cours d'exécution:

    $ 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 ksh, yashet zsh(également bashmais uniquement pour les caractères à octet unique), prennent en charge les alnums dans les paramètres régionaux actuels, pas seulement ceux en ASCII.

    $ Stéphane=1
    $ echo "$Stéphane"
    1
    

    Dans ces shells, vous pouvez modifier les paramètres régionaux pour considérer la plupart des caractères comme des caractères alpha, mais cela ne fonctionnerait pas pour les caractères ASCII tels que .. Vous pouvez tromper zshou kshpenser que £c'est une lettre, mais pas cela .ni aucun autre caractère ASCII (où autoriser les caractères dans les noms de variables est concerné, pas pour le [[:alpha:]]glob par exemple).

  • ksh93a des variables spéciales dont le nom contient un point comme ${.sh.version}, mais celles-ci ne sont pas mappées à des variables d'environnement et sont spéciales. Le .est de s'assurer qu'il ne soit pas en conflit avec d'autres variables. Si elle avait choisi de l' appeler $sh_version, il aurait pu les scripts potentiellement cassés qui a utilisé cette variable déjà (voir par exemple comment zsha des problèmes avec son $pathou des $commandsvariables tableau spécial / hachage (à la csh) qui brisent certains scripts).

Notez que , en plus de coquilles qui ne supportent pas ces variables, des coquilles comme pdksh / mksh font supprimer les de l'environnement qu'ils reçoivent ( bashsupprime l'un avec un nom vide, ash, kshet bashsupprimer les chaînes d'environnement qui ne contiennent pas de =caractère):

$ 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 %%%
%%%

En résumé, le mieux est de coller avec les noms de variables pris en charge par la plupart des coquilles et même essayer d'utiliser les majuscules pour les variables d'environnement (et minuscules ou majuscules et minuscules pour les variables shell non exportées) en évitant ceux qui sont spéciaux dans des coquilles (comme IFS, PS1, BASH_VERSION...)

Si vous devez définir une telle variable dans un shell qui ne la prend pas en charge, mais ne la supprime pas, vous pouvez soit réexécuter vous-même, avec quelque chose comme:

#! /bin/ksh -
perl -e 'exit 1 unless defined($ENV{"a.b"})' || exec env a.b=%%% "$0" "$@"

(Évidemment, si vous devez le faire au milieu du script, cela ne vous aidera pas, mais vous pourrez alors examiner cette approche pour enregistrer et restaurer l'environnement d'exécution du shell sur une nouvelle exécution). Ou essayez l'approche du débogueur:

gdb --batch-silent -ex 'call putenv("a.b=%%%")' --pid="$$"

(que l' on semble travailler avec zsh, yash, cshet tcshsur Linux AMD64, mais pas avec l' une des autres coquilles que j'ai essayé ( mksh, ksh93, bash, dash)).

Stéphane Chazelas
la source
1
mksh(and pdksh) en effet, les processus d’environnement qu’ils génèrent sont entièrement récupérés, en utilisant uniquement les paramètres exportés dans l’environnement d’exécution du shell actuel, il n’existe donc aucun moyen de transmettre ces variables à travers ces shells. (Notez que les variables qui sont passées sont sujettes à changement. Par exemple, je mksh
prévois
0

Comme le signalent d’autres publications, les shells les plus courants ne permettent pas de définir des variables d’environnement avec des points dans le nom. Cependant, j'ai constaté des situations, impliquant notamment des programmes Docker et invoqués, dans lesquelles le logiciel nécessitait des valeurs de clé avec des points.

Toutefois, dans chacune de ces situations, ces paires clé-valeur peuvent être transmises au programme par d'autres moyens que les seules variables d'environnement. Par exemple, dans Ant, vous pouvez utiliser le "-propertyfile (nom du fichier)" pour transmettre une collection de valeurs-clés au format de fichier de propriétés. Confd permet "-backend file -file (fichier yaml)".

J'ai transmis les variables d'environnement sous la forme "C__any_value = 'my.property.key = la valeur'". J'ai ensuite basculé l'invocation du programme pour générer d'abord le fichier:

set | awk -- 'BEGIN { FS="'\''" } /^C__/ {print $2}' > my-key-values.txt

La setcommande, dans Borne Shell, affichera chaque propriété sur une ligne distincte du formulaire.

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

La awkcommande ne traitera que les variables d'environnement commençant par C__, puis extraira les valeurs contenues dans les guillemets simples.

Cette méthode nécessite que la valeur de la variable d'environnement soit définie sous la forme précise requise par le programme de traitement. En outre, si votre valeur de propriété ou votre clé contient des guillemets simples, vous devrez alors remplacer le caractère de séparation de champ awk par un élément qui n'apparaîtra pas et entourer la valeur de ce caractère. Par exemple, pour utiliser %comme séparateur:

$ C__1="%my.key=the'value%"
$ set | awk -- 'BEGIN { FS="%" } /^C__/ {print $2}'
my.key=the'"'"'value

(la sortie précise dépendra de votre shell.) Vous devrez prendre des mesures supplémentaires pour décoder l'échappement de la citation.

Groboclown
la source