如何导出其中带有点的变量。我尝试时得到“无效的变量名”:
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
如何导出其中带有点的变量。我尝试时得到“无效的变量名”:
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
Answers:
至少对于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
定义它。但是话又说回来,您将无法使用常规Shell语法访问它。在这种情况下,您可能需要另一种语言,如perl:
perl -e 'print $ENV{"my.home"}'
例如
env "my.home=/tmp/someDir" perl -le 'print $ENV{"my.home"}'
应该打印您的路径。
ANT_OPTS
或〜/ .antrc的环境变量配置的。ant本身不需要奇怪的环境变量名称。
尽管环境变量可以具有不包含等号或空字节的任何名称(包括空字符串),但是Shell会将环境变量映射到Shell变量,并且在大多数Shell中,变量名称仅限于ASCII字母数字字符,_
并且第一个字符可以吨是数字(除了位置参数和其他特殊的像$*
,$-
,$@
,...,(其中未映射到相应的环境变量))。还请注意,某些变量是由Shell 保留/专用的。
例外情况:
该rc
外壳及其衍生物喜欢es
和akanga
支持任何名称,除了空字符串,和那些所有数字或含有=
字符(始终所有的变量导出到环境和特殊变量提防喜欢*
,status
,pid
...):
; '%$£"' = test
; echo $'%$£"'
test
; '' = x
zero-length variable name
;
但是,对于在执行命令的环境中传递的名称不包含数字的变量或数组,它使用自己的编码:
$ 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那些支持alnums。
$ Stéphane=1
$ echo "$Stéphane"
1
在这些Shell中,您可以更改语言环境以将大多数字符视为字母,但仍然不适用于ASCII字符.
。您可以愚弄zsh
或ksh
认为£
一个字母是字母,但不能认为它是字母.
或任何其他ASCII字符(涉及变量名中的字符,[[:alpha:]]
例如,不适用于glob)。
ksh93
有一些特殊变量,其名称包含一个点,如${.sh.version}
,但是这些变量未映射到环境变量并且是特殊的。的.
是确保它不会与其他变量冲突。如果选择调用它$sh_version
,那么它可能已经损坏了已经使用该变量的脚本(例如,查看zsh
其脚本$path
或$commands
特殊的数组/哈希变量(la csh)如何出现问题,从而破坏了某些脚本)。
请注意,除了不支持这些变量的外壳程序外,某些外壳程序(如pdksh / mksh)的确会将其从其接收的环境中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 %%%
%%%
总结起来,最好是坚持使用由大多数shell支持变量名,甚至尝试使用环境变量上的情况下(和小写或混合大小写不导出的shell变量)避免那些在炮弹特殊(如IFS
,PS1
,BASH_VERSION
...)。
如果确实需要在不支持它们但不丢弃它们的shell中设置此类变量,则可以使用以下方法重新执行自己:
#! /bin/ksh -
perl -e 'exit 1 unless defined($ENV{"a.b"})' || exec env a.b=%%% "$0" "$@"
(当然,如果你需要做的是在脚本中,这不会帮助,但你可以再看看这种方法来保存并在重新执行中恢复shell执行环境)。或尝试使用调试器方法:
gdb --batch-silent -ex 'call putenv("a.b=%%%")' --pid="$$"
(一个似乎与工作zsh
,yash
,csh
并tcsh
在Linux AMD64,但不与任何其它shell我想(的mksh
,ksh93
,bash
,dash
))。
mksh
(和pdksh
)确实构造了它们产生的环境进程,它们仅使用当前shell执行环境中导出的那些参数完全从头获得,因此无法通过这些shell传递这些变量。(请注意,这两个变量的传递受到变化;例如我打算支持阵列出口mksh
的某一天。)
正如其他文章所指出的那样,最常见的shell不允许在名称中使用句点来设置环境变量。但是,我发现了一些情况,特别是涉及Docker和调用的程序的情况,其中该软件需要带有句点的键值。
但是,在每种情况下,这些键值对都可以通过环境变量以外的其他方式传递给程序。例如,在Ant中,您可以使用“ -propertyfile(文件名)”来传递属性文件格式的键值集合。Confd允许使用“ -backend file -file(yaml文件)”。
我以“ C__any_value ='my.property.key =值'”的形式传递了环境变量。然后,我将程序调用切换为首先生成文件:
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
(精确的输出将取决于您的shell。)您将需要采取额外的步骤来解码引号转义。