我想在 bash 中搜索所有定义的函数以获取一些搜索字符串。下面是一个开始,但我想在下一行消除所有没有$1
跟空格的术语(即消除在该函数的主体中没有找到的所有条目)。
fu() { declare -f | grep -e \(\) -e $1; }
例如这个输出:
...
tt ()
untargz ()
urlfix ()
ver ()
[ -f /etc/lsb-release ] && RELEASE="$(cat /etc/lsb-release | grep DESCRIPTION | sed 's/^.*=//g' | sed 's/\"//g') ";
vi. ()
vi.su ()
...
会减少到
...
ver ()
[ -f /etc/lsb-release ] && RELEASE="$(cat /etc/lsb-release | grep DESCRIPTION | sed 's/^.*=//g' | sed 's/\"//g') ";
...
如果可以确定并完整显示每个匹配函数,则更好的方法(如果可能)将是。
我的设想大致为:
- 收集函数的名称及其正文中的搜索字符串(函数的名称始终是匹配前一行上的一个单词,从 at 开始,
^
后跟一个空格,然后以 结尾的行()$
),然后command -V
在其中的每一个上使用名称,或者,再做declare -f
一次,但这次,使用这些名称并将它们之后的所有内容从{
to匹配}
(在哪里{
和}
在单行上)^
- 我知道 grep/awk/sed 可以对那些有这些知识的人做惊人的事情.
最终结果将运行fu awk
,它将向我显示函数awk
体中包含的每个函数的定义。
awk
想到管道接收端的以下命令:buf
这个想法是在解析 的输出时将每个函数的声明和主体存储在缓冲区中declare -f
,但仅在找到搜索字符串时才打印缓冲区。()
. 如果在解析前一个函数时找到匹配项(由标志为 1 表示),将打印m
缓冲区。buf
缓冲区和标志都将被重置。awk
变量传递给程序srch
。如果在当前行找到(index
函数返回非零结果),则m
标志设置为 1,但前提是我们不在函数声明开始的行(表示buf
不为空),否则匹配在函数名称中也将计算在内。buf
,并通过输出记录分隔符ORS
(默认为换行符)与先前的内容分隔。笔记
index()
该程序使用 的函数执行全字符串搜索awk
。如果您希望搜索基于正则表达式匹配,则需要将条件从至
(但与往常一样,请注意搜索包含对正则表达式具有特殊含义的字符的字符串变得更加麻烦)。
对于那些想要
zsh
在<dummy>
覆盖没有匹配功能的情况。或者更清洁的方式:在
bash
中,您可以执行类似的操作:尽管这是非常低效的,因为函数名称列表一次读取一个字节(因为
read
' 的输入是管道),并且每个函数都派生一个进程。它可以通过以下方式进行优化:readarray
,相反read
,不需要一次读取一个字节的输入,因为它无论如何都会消耗所有输入。我们用 NUL 字符分隔函数定义,因为无论如何bash
(与 相反zsh
)不能将该字符存储在其函数定义/名称或变量内容中,然后我们可以使用readarray -td ''
(这需要 bash-4.4+)将其分解为一个数组。这避免了必须依赖诸如存在的启发式算法
()
(这也很可能出现在函数的主体中)来猜测每个函数定义在typeset -f
.