编辑:
我意识到我错误地理解了这篇文章中的一个中心假设:语法${!prefix@}
无法获取函数名称,而只能获取变量。因此,${!prefix@}
即使使用下划线,也无法返回函数名称。因此,我对下面的粗体问题的答案是明确的“否”。 尽管如此,埃德加下面的回答对于那些想要根据某个前缀获取函数名称列表的人来说还是很有帮助的。
原问题
这bash参数扩展手册为我们提供了一种获取当前环境中以某个前缀开头的所有变量(非函数)列表的方法:
${!prefix@}
我有一堆以 开头的函数foo-
,例如foo-setup
、foo-run
、foo-initialize
等。现在,我尝试过但未能获得${!foo-@}
它的变体以返回以 开头的函数列表foo-
。我尝试过${!foo\-@}
、、、、和许多其他变体"${!foo\-@}"
。我知道连字符在参数扩展中有其自己的含义,因此预计如果没有一些转义或类似的操作,它将无法工作。但我也希望 Bash 应该具有在任何上下文中转义特殊字符的机制,包括在参数扩展期间,除非......也许这里不是这种情况?"${!foo-@}"
bar=foo; ${!${bar}-@}
-
(我研究过这样一个事实,如果我想要跨平台兼容性,我应该避免使用连字符的函数名称。我同意这一点。而且,用连字符而不是下划线输入函数要流畅得多……)
因此,本着探究的精神,我提出这个问题:有没有什么方法可以使用本机参数扩展来获取所有以连字符前缀开头的已定义函数(或一般的名称引用)列表?也许解决方案是以我不知道的方式转义连字符?
(如果没有,是否有替代方法,也许可以获取完整的变量列表,然后过滤它们以仅留下具有所需连字符前缀的变量?)
答案1
有替代方法吗?
是的,您可以使用declare
或compgen
来获取已定义函数的列表:
解决方案1(它将匹配包含指定字符串/模式的函数)
declare -F | grep -o 'foo-.*'
#or
compgen -A function | grep 'foo-'
解决方案2(特别是匹配前缀/以某些字符串/模式开头)
declare -F | cut -d ' ' -f3 | grep '^foo-'
#or
compgen -A function | grep '^foo-'
关于使用参数扩展,我不确定是否可以获取函数名称。根据手册,它似乎只适用于变量:
${!前缀*}
${!前缀@}
扩展为名称以前缀开头的变量名称,并以 IFS 特殊变量的第一个字符分隔。当使用“@”并且扩展出现在双引号内时,每个变量名称都会扩展为一个单独的单词。
还有你所说的:
诚然,如果我重命名所有函数,将它们的 foo- 前缀更改为 foo_,那么 ${!foo_@} 确实可以获取所有函数。
我想知道你是否尝试过并且它有效(我不认为),因为我用一些功能测试了它但没有工作。
当然,您不能使用连字符定义变量-
,因此不可能使用${prefix-@}
or ${prefix-*}
。
答案2
为了完整起见,如果您想获取与 zsh 中的模式匹配的函数名称列表,您可以这样做:
typeset +f -m 'foo-*'
(替换+f
为-f
还可以查看这些函数的定义)。
但请注意,zsh 中的函数名称可以是任何字节序列(毕竟它们与命令位于同一命名空间中,文件路径可以是非空字节的任何非空序列),因此输出不可进行后处理可靠。
但是,您可以通过查找捕获模式的k
特殊$functions
关联数组的眼睛来获取数组中的列表:M
foo_functions=( ${(Mk)functions:#foo-*} )
具有奇怪命名函数的示例:
$ typeset +f -m 'foo-*'
foo-a
b
c
foo-barbaz
$ print -rC1 -- ${(q)foo_functions}
foo-a$'\n'b$'\n'c
foo-bar$'\0'baz