TL;博士:是否有zsh
相当于 Ksh/Bash 的"${!varnamepfx@}"
扩展?
例如,如果我有以下变量set
:
[...]
foo='random value'
bar=$'amazing\n value'
baz='that other value'
[...]
然后通过printf -- %s\\n "${!ba@}"
在 Bash 中请求我得到:
bar
baz
我一直在阅读zsh
手动的但没能到找到任何东西像上面的语法一样直接。我能采取的最好方法是以下嵌套扩展:
(对于上面的例子)
printf -- %s\\n "${(M)${${(f)$(set)}[@]%%=*}[@]:#ba*}"
它似乎可靠地完成了这项工作(至少在 MacOS Catalina 的 zsh v5.3 上),但看起来相当复杂,我也想知道$(set)
其中的命令替换是否真的产生了一个进程,或者是通过zsh
.
诚然,到目前为止,我已经排除了(因此没有考虑)通过完成系统来完成这项工作,因为对于这样一个简单的任务来说,这似乎有点矫枉过正。
答案1
另一个匹配按键的选项$parameter
特殊关联数组是使用I
下标标志:
$ print -rC1 - $parameters[(I)ba*]
bar
baz
那是一个关联数组运算符产生列表/数组,而 @Gille${(kM)parameters:#ba*}
是列表/数组运算符应用于关联数组的键也会产生列表/数组。在本例中,最终结果本质上是相同的。
如果您只需要记住一个,那么${(M)array:#pattern}
-for grep
-arrays 是更有用的,因为它更通用。与它相比无法做到的事情数组下标标志是匹配键并返回相应的值或匹配值并返回相应的键。
您可以将两者结合起来,如下所示:
$ print -rC1 - ${(Mk)parameters[(R)array*]:#pa*}
path
patchars
pa
这里返回以(开头的数组的名称价值观的与和$parameters
相匹配array*
键反对pa*
)。
当然,您可以对所有zsh
内省变量($aliases
, $commands
, $functions
, $builtins
, $modules
, $history
...)执行此操作
对于其中一些,您还可以使用-m pattern
相应内置函数(whence -m
, alias -m
, autoload -m
, fc -m
...)的(匹配)选项进行查询,但与 for bash
's一样compgen
,您无法可靠地后处理它们的输出,因为它是基于行的,而他们报告的一些内容可能包含换行符。
答案2
Zsh 没有特殊的语法来过滤变量名称。只需结合parameters
关联数组和参数扩展功能:${(k)…}
获取键(即参数名称),${…:#…}
根据模式进行过滤,并${(M)…}
保留匹配项而不是删除匹配项。
printf '%s\n' ${(kM)parameters:#ba*}