Хоча змінні середовища можуть мати будь-яке ім'я (включаючи порожню рядок), що не містить знака рівності або нульового байта, оболонки відображають змінні середовища в змінні оболонки, а в більшості оболонок імена змінних обмежуються буквено-цифровими символами 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
але тільки для одного байта символів) Підтримка alnums в поточній локалі, не тільки ASCII з них.
$ Stéphane=1
$ echo "$Stéphane"
1
У цих оболонках ви можете змінити локаль, щоб вважати більшість символів альфа, але все одно це не працюватиме як символи ASCII .
. Ви можете обдурити zsh
або ksh
подумати £
про букву, але не той .
чи будь-який інший символ ASCII (якщо це стосується дозволу символів із змінними іменами, а не для [[:alpha:]]
глобуса).
ksh93
має спеціальні змінні, ім'я яких містить крапку ${.sh.version}
, але вони не відображаються на змінні середовища та є спеціальними. Потрібно .
переконатися, що він не суперечить іншим змінним. Якби він вирішив викликати його $sh_version
, тоді він міг би мати потенційно зламані сценарії, які вже використовували цю змінну (див., Наприклад zsh
, проблеми з її $path
або $commands
спеціальними змінними масиву / хеш (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
)).