我希望在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') ";
...一个甚至更好的方法(如果可能的话)将是,如果每个匹配的功能可以确定和充分显示。
我的设想大致是:
^开始,然后是以()$结尾的行),然后对每个名称使用command -V,OR,再次执行declare -f,但这次,使用这些名称并匹配从{到} ( {和}在^上都是单行)的所有内容--我知道grep/awk/sed可以对那些有这种知识的人做令人惊奇的事情。最终结果将是运行fu awk,它将显示函数正文中包含awk的每个函数的定义。
发布于 2021-10-05 14:38:45
想到管道接收端的以下awk命令:
declare -f | awk -v srch="pattern" 'NF==2 && $2=="()"{if (m) print buf; buf=""; m=0}
buf && index($0,srch){m=1}
{buf=buf ORS $0}
END{if (m) print buf}'其思想是在解析buf的输出时将每个函数的声明和正文存储在缓冲区declare -f中,但只有在找到搜索字符串时才打印缓冲区。
()。如果在解析前一个函数(由标志m为1指示)时找到匹配,则将打印缓冲区buf。缓冲区和标志都将被重置。awk变量srch的形式传递给程序。如果在当前行中找到它( index函数返回一个非零的结果),则m标志设置为1,但只有当我们不在函数声明开始的行(由buf不为空表示)时,否则函数名称中的匹配也将计算在内。buf,并由输出记录分隔符ORS (默认为换行符)与以前的内容分隔开来。注
该程序通过使用index()的awk函数执行全字符串搜索.如果希望搜索基于正则表达式匹配,则需要将条件更改为
index($0,srch)至
$0~srch(但是,与往常一样,要注意的是,搜索包含对正则表达式具有特殊意义的字符的字符串会变得更麻烦)。
发布于 2021-10-05 15:30:26
对于那些在zsh中做同样事情的人来说,要获得其身体与模式匹配的函数的函数定义,您可以这样做:
typeset -f '' ${(k)functions[(R)pattern]}用于覆盖没有匹配函数的情况的。或者一种更干净的方式:
() { (($#)) && typeset -f -- "$@"; } ${(k)functions[(R)pattern]}在bash中,您可以使用以下方法执行类似的操作:
compgen -A function | (
ret=1
while IFS= read -r fn; do
def=$(typeset -f -- "$fn") &&
[[ ${def#*'()'} = pattern ]] &&
printf '%s\n' "$def" &&
ret=0
done
exit "$ret"
)虽然这样做效率很低,因为函数名列表一次只读取一个字节(因为read的S输入是一个管道),而且每个函数都要分叉一个进程。
compgen -A function | (
readarray -t functions
for fn in "${functions[@]}"; do
typeset -f -- "$fn" && printf '\0'
done
) | (
ret=1
readarray -td '' fn_definitions
for def in "${fn_definitions[@]}"; do
[[ ${def#*'()'} = pattern ]] &&
printf '%s\n' "$def" &&
ret=0
done
exit "$ret"
)与readarray相反,read不需要每次读取一个字节的输入,因为它无论如何都会消耗所有的输入。我们用NUL字符分隔函数定义,因为无论如何,bash (与zsh相反)不能将该字符存储在函数定义/名称或变量内容中,然后可以使用readarray -td '' (这需要bash-4.4+)将其分解为数组。
这避免了依赖启发式方法,例如()的存在(很可能也会出现在函数的主体中)来猜测typeset -f输出中每个函数定义从哪里开始的。
https://unix.stackexchange.com/questions/671949
复制相似问题