Экспорт переменной с точкой (.) В ней

39

Как экспортировать переменную, в которой есть точка. Я получаю «недопустимое имя переменной», когда я пытался:

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

Даже экранирование метасимволов (.) Не помогло

$ export my\.home=/tmp/someDir
export: my.home=/tmp/someDir: is not an identifier
user1587504
источник
дубликат unix.stackexchange.com/questions/23659/…
мичас
1
к сожалению, его не было в списке, когда я набирал / искал похожий вопрос. извиняюсь. ..
user1587504

Ответы:

50

По крайней мере, для bashсправочной страницы определяется синтаксис экспорта как:

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

Он также определяет «имя» как:

   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.

Следовательно, вы действительно не можете определить переменную, так my.homeкак она не является допустимым идентификатором.

Я очень уверен, что ваш ksh имеет очень похожее определение идентификатора и поэтому не допускает такого рода переменных. (Посмотрите его справочную страницу.)

Я также очень уверен, что существует какой-то общий стандарт (POSIX?), Определяющий, что разрешено в качестве идентификатора (и, следовательно, имени переменной).


Если вам действительно нужна переменная такого типа, вы можете использовать что-то вроде

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

чтобы определить это в любом случае. Но опять же, вы не сможете получить к нему доступ, используя обычный синтаксис оболочки. В этом случае вам, вероятно, понадобится другой язык, такой как perl:

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

Например

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

должен напечатать ваш путь.

Михась
источник
Это из-за интеграции муравья. И, к сожалению, это не позволяет устанавливать / экспортировать переменные из unix. Принимая ваш ответ. ..
user1587504
1
Муравей обычно настраивается с помощью одной переменной окружения ANT_OPTSили ~ / .antrc. Нет необходимости в странных именах переменных среды для самого муравья.
Михас
8

В то время как переменные окружения могут иметь любое имя (включая пустую строку), не содержащее знака равенства или нулевого байта, оболочки отображают переменные среды на переменные оболочки, и в большинстве оболочек имена переменных ограничиваются буквенно-цифровыми символами ASCII, и _там, где первый символ может ' т быть цифрой (для позиционных параметров и других специальных из них , как , за исключением $*, $-, $@, ..., (которые не отображаются в соответствующих переменных окружения)). Также обратите внимание, что некоторые переменные зарезервированы / специально для / оболочки.

Исключения к этому:

  • rcОболочки и ее производные , как esи akangaподдерживать любое имя , кроме пустой строки, и те, которые все-цифровые или содержать =символы (и всегда экспортировать все свои переменные среды, и остерегайтесь специальными переменными , такие как *, status, pid...):

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

    Тем не менее, он использует свою собственную кодировку для переменных, чье имя не содержит символов alnums или для массивов при передаче в среде выполняемых команд:

    $ 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, yashа zshтакже ( bashно только для однобайтовых символов) поддерживают текущую локалию, а не только ASCII.

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

    В этих оболочках вы можете изменить локаль, чтобы большинство символов считалось альфа-каналом, но все же это не сработало бы для символов ASCII, таких как .. Вы можете обмануть zshили kshдумать, £что это буква, но не тот .или любой другой символ ASCII (если речь идет о разрешении символов в именах переменных, например, не о [[:alpha:]]глобусе).

  • ksh93имеет специальные переменные, имя которых содержит точку, похожую на точку ${.sh.version}, но они не отображаются на переменные окружения и являются специальными. Необходимо .убедиться, что он не конфликтует с другими переменными. Если бы он решил вызвать его $sh_version, он мог бы иметь потенциально сломанные сценарии, которые уже использовали эту переменную (см., Например, как возникают zshпроблемы с его $pathили $commandsспециальными переменными array / hash (a la csh), которые нарушают некоторые сценарии).

Следует отметить , что в дополнение к оболочках , не поддерживающих эти переменные, некоторые оболочки , как pdksh / МКШ сделать удалить их из окружающей среды , которую они получают ( bashудаляет один с пустым именем, ash, kshи bashудалить эти строки окружения , которые не содержат =символов):

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

Подводя итог, лучше всего придерживаться имен переменных , поддерживаемых большинством оболочек и даже пытаются использовать верхний регистр для переменных окружения (и нижний регистр или смешанный регистр для не экспортируемых переменных оболочки) избегать тех , которые являются особенными в оболочках (например IFS, PS1, BASH_VERSION...).

Если вам нужно установить такую ​​переменную в оболочке, которая не поддерживает их, но не отбрасывает их, вы можете либо выполнить себя заново, например:

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

(очевидно, если вам нужно сделать это в середине скрипта, это не поможет, но вы могли бы тогда взглянуть на этот подход, чтобы сохранить и восстановить среду выполнения оболочки через повторное выполнение). Или попробуйте подход отладчика:

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

(что один , кажется, работает с zsh, yash, cshи tcshна Linux amd64, но не с какой - либо из других оболочек я попробовал ( mksh, ksh93, bash, dash)).

Стефан Шазелас
источник
1
mkshpdksh) действительно конструировать процессы среды, которые они порождают, получают с нуля, используя только те параметры, которые экспортируются в текущую среду выполнения оболочки, поэтому невозможно передать эти переменные через эти оболочки. (Обратите внимание, что передаваемые переменные могут быть изменены; например, я планирую поддерживать экспорт массивов в течение mksh
одного
0

Как отмечают другие посты, самые распространенные оболочки не позволяют устанавливать переменные среды с точками в имени. Однако я обнаружил ситуации, особенно связанные с Docker и вызываемыми программами, когда программное обеспечение требовало значения ключей с точками.

Однако в каждой из этих ситуаций эти пары ключ-значение могут быть переданы в программу другими способами, а не только переменными среды. Например, в Ant вы можете использовать «-propertyfile (filename)» для передачи отформатированной в файл свойств коллекции ключей-значений. Confd позволяет использовать «-backend file -file (yaml file)».

Я передал переменные окружения в форме "C__any_value = 'my.property.key = the value'". Затем я переключил вызов программы, чтобы сначала сгенерировать файл:

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

Команда setв Borne Shell выведет каждое свойство в отдельной строке в форме

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

Команда awkбудет обрабатывать только переменные среды, начиная с C__, а затем извлекать значения, содержащиеся в одинарных кавычках.

Этот метод требует, чтобы значение переменной среды было установлено в точном виде, который требуется программе обработки. Кроме того, если значение или ключ вашего свойства будут содержать одинарные кавычки, вам потребуется изменить символ разделителя полей awk на что-то, что, как вы знаете, не будет отображаться, и окружить значение этим символом. Например, чтобы использовать %в качестве разделителя:

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

(Точный вывод будет зависеть от вашей оболочки.) Вам нужно будет предпринять дополнительные шаги для декодирования экранирующей кавычки.

Groboclown
источник