我正在阅读《初学者打击指南》。它说:


如果PARAMETER的第一个字符是一个感叹号,则Bash使用从PARAMETER其余部分形成的变量值作为变量名;然后扩展此变量,并在其余替换中使用该值,而不是PARAMETER本身的值。这称为间接扩展。


给出的示例是:


franky ~> echo ${!N*}
NNTPPORT NNTPSERVER NPX_PLUGIN_PATH



I在这里不太了解:


PARAMETER其余部分形成的变量的值


由于PARAMETER只是!N*,则


PARAMETER的其余部分


只是N*。这如何形成变量? Bash在那里搜索了所有可能的命令吗?

#1 楼

如果阅读bash手册页,则基本上可以确认您所说的内容:

如果参数的第一个字符是感叹号(!),则会引入变量间接寻址级别。 Bash使用由其余参数形成的变量的值作为变量的名称;然后扩展此变量,并在其余替换中使用该值,而不是参数本身的值。这称为间接扩展。

但是,请从此处继续阅读:

以下例外是${!prefix*}${!name[@]}的扩展。
${!prefix*}名称匹配的前缀。扩展为名称以前缀开头的变量的名称,并用特殊变量IFS的第一个字符分隔。

换句话说,您的特殊示例${!N*}是引用的规则的例外。但是,它确实可以按预期的情况工作,例如:
$ export xyzzy=plugh ; export plugh=cave

$ echo ${xyzzy}  # normal, xyzzy to plugh
plugh

$ echo ${!xyzzy} # indirection, xyzzy to plugh to cave
cave


评论


感谢你的回答。我读过越多的《初学者入门指南》,就越要问自己作者是否理解她写的东西。

–LRDPRDX
6月2日14:24



#2 楼

当给定的“间接”以*结尾时,似乎有一个例外,就像这里一样。在这种情况下,它会给出以您指定的部分开头的所有变量名(此处为N)。
Bash可以这样做,因为它可以跟踪变量并知道存在哪些变量。 this:
说我有一个变量$VARIABLE设置为42,我还有另一个变量$NAME设置为VARIABLE${!NAME}会给我42。您使用一个变量的值告诉您另一个变量的名称:

$ NAME="VARIABLE"
$ VARIABLE=42
$ echo ${!NAME}
42


评论


哇,谁知道获得生命,宇宙和一切意义的答案是如此容易!

– KomodoDave
2014年5月8日14:12

#3 楼

是的,它在!之后搜索变量的所有可能扩展。如果您已完成以下操作:

echo ${!NP*}


您将只得到NPX_PLUGIN_PATH

请考虑以下示例:

:~> export myVar="hi"
:~> echo ${!my*}
    myVar
:~> export ${!my*}="bye"
:~> echo $myVar
    bye


评论


是否将与my *匹配的其他变量也设置为“再见”?

–安东尼
16-10-13在18:05

@Anthony我尝试过,如果$ {!my *}扩展为myA,myB,则myA将使用其当前值导出,并且myB设置为“ bye”并导出。不是很有用。

– GKFX
16-10-17在20:50

#4 楼

您在间接处理中遇到了一个异常,如果最后一个字符是*,则将返回所有具有前面给定前缀的变量。

评论


因此,除了*大小写,还和$ {$ {VAR}}一样吗?

– chronospoon
2014年10月13日17:56

@chronospoon $ {$ {VAR}}(不久后可以写成$ {$ VAR})是不合法的,因为$ VAR返回一个字符串,该字符串不能跟随$符号。要将字符串用作变量名,您需要引入一个间接级别(如原始问题本身所引用),即,可以使用$ {!VAR},它完全符合您的期望(错误但可以理解)$ { $ VAR}可以。

– Enlico
18年6月7日在11:51



#5 楼

您可以参考Bash的此GNU文档以获取权威信息

https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html#Shell-Parameter-扩展

但是基本上,${!prefix*}上不执行间接扩展,这是例外之一,在您的示例中,N是前缀。

文档将解释什么是间接扩展在bash中