什么是间接扩张?$ {!var*}是什么意思?

ath*_*hos 70 bash indirection

我正在读" Bash初学者指南 ".它说:

如果第一个字符PARAMETER是感叹号,则Bash使用由其余部分形成的变量的值作为变量PARAMETER的名称; 然后展开此变量,并将该值用于替换的其余部分,而不是其PARAMETER自身的值.这被称为间接扩张.

给出的例子是:

franky ~> echo ${!N*}
NNTPPORT NNTPSERVER NPX_PLUGIN_PATH
Run Code Online (Sandbox Code Playgroud)

我在这里不太明白:

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

由于PARAMETER是刚刚!N*的话

其余的 PARAMETER

只是N*.怎么会形成一个变量?Bash在那里搜索了所有可能的命令吗?

pax*_*blo 90

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

如果参数的第一个字符是感叹号(!),则引入一个变量间接的级别.Bash使用从参数的其余部分形成的变量的值作为变量的名称; 然后展开此变量,并将该值用于替换的其余部分,而不是参数本身的值.这被称为间接扩张.

但是,从那里继续阅读:

对此的例外是以下的扩展${!prefix*}${!name[@]}描述.

${!prefix*}名称匹配前缀.扩展为名称以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
Run Code Online (Sandbox Code Playgroud)

  • 感谢你的回答。我读《Bash 初学者指南》越多,我就越问自己作者是否理解她所写的内容。 (4认同)

F. *_*uri 20

bash间接和/或nameref

关于这个问题迟到了,因为没有其他答案讲述nameref ...

使用${!var} 间接语法:

~$ someVariable='Some content'
~$ var=someVariable

~$ echo $var
someVariable

~$ echo ${!var}
Some content
Run Code Online (Sandbox Code Playgroud)

使用namref ( declare -n) 语法

通过使用nameref,您不仅可以显示变量的内容,还可以填充变量并获取或设置属性。

~$ someVariable='Some content'
~$ declare -n var=someVariable
~$ echo $var
Some content
~$ echo ${var@A}
someVariable='Some content'
Run Code Online (Sandbox Code Playgroud)

此语法对于函数很有用:

~$ someVariable='Some content'
~$ var=someVariable

~$ echo $var
someVariable

~$ echo ${!var}
Some content
Run Code Online (Sandbox Code Playgroud)

(注:此函数只是一个示例。这不会正确扩展数组关联数组!)

然后

~$ someVar='Hello world!'
~$ showVarDetail someVar
Variable '$someVar' is 12 len, has [] flags and contain: Hello\ world\!

~$ declare -r PI=3.14159265358979323844
~$ showVarDetail PI
Variable '$PI' is 22 len, has [r] flags and contain: 3.14159265358979323844

~$ declare -ir answerOfUltimateQestionOfLiveUniverseAndEverything=42
~$ showVarDetail answerOfUltimateQestionOfLiveUniverseAndEverything
Variable '$answerOfUltimateQestionOfLiveUniverseAndEverything' is 2 len, has [ir
] flags and contain: 42
Run Code Online (Sandbox Code Playgroud)

使用nameref填充变量值

这可以起到双向作用!

这是一个使用两个变量名作为参数运行的小示例函数。第一个变量应包含一个字符串,第二个变量将由第一个变量内容的第一个字符填充,然后第一个变量内容将移动 1 个字符:

~$ someVariable='Some content'
~$ declare -n var=someVariable
~$ echo $var
Some content
~$ echo ${var@A}
someVariable='Some content'
Run Code Online (Sandbox Code Playgroud)
function showVarDetail() {
    local -n var=$1
    printf 'Variable \47\44%s\47 is %d len, has [%s] flags and contain: %q\n' \
        "$1" "${#var}" "${var@a}" "$var"
}
Run Code Online (Sandbox Code Playgroud)

然后

~$ someVar='Hello world!'

~$ shift1char someVar someChar

~$ showVarDetail someVar
Variable '$someVar' is 11 len, has [] flags and contain: ello\ world\!

~$ showVarDetail someChar
Variable '$someChar' is 1 len, has [] flags and contain: H
Run Code Online (Sandbox Code Playgroud)

经过一些小的修改:

~$ someVar='Hello world!'
~$ showVarDetail someVar
Variable '$someVar' is 12 len, has [] flags and contain: Hello\ world\!

~$ declare -r PI=3.14159265358979323844
~$ showVarDetail PI
Variable '$PI' is 22 len, has [r] flags and contain: 3.14159265358979323844

~$ declare -ir answerOfUltimateQestionOfLiveUniverseAndEverything=42
~$ showVarDetail answerOfUltimateQestionOfLiveUniverseAndEverything
Variable '$answerOfUltimateQestionOfLiveUniverseAndEverything' is 2 len, has [ir
] flags and contain: 42
Run Code Online (Sandbox Code Playgroud)

应该产生:

shift1char <variable string source> <variable target>
Run Code Online (Sandbox Code Playgroud)


Kev*_*vin 19

当给定的"间接"以a结尾时,似乎有一个例外*,就像在这里一样.在这种情况下,它提供以您指定的部分(N此处)开头的所有变量名称.Bash可以做到这一点,因为它跟踪变量并知道存在哪些变量.

真正的间接是这样的:
假设我有一个变量$VARIABLE设置42,我有另一个变量$NAME设置为VARIABLE. ${!NAME}会给我的42.您使用一个变量的值来告诉您另一个变量的名称:

$ NAME="VARIABLE"
$ VARIABLE=42
$ echo ${!NAME}
42
Run Code Online (Sandbox Code Playgroud)