列出 Bash 中定义的函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2625783/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Listing defined functions in Bash
提问by Charles Duffy
I'm trying to write some code in bash which uses introspection to select the appropriate function to call.
我正在尝试用 bash 编写一些代码,它使用自省来选择要调用的适当函数。
Determining the candidates requires knowing which functions are defined. It's easy to list defined variablesin bash using only parameter expansion:
确定候选者需要知道定义了哪些函数。只使用参数扩展就可以很容易地在 bash 中列出定义的变量:
$ prefix_foo="one"
$ prefix_bar="two"
$ echo "${!prefix_*}"
prefix_bar prefix_foo
However, doing this for functionsappears to require filtering the output of set -- a much more haphazard approach.
但是,对函数执行此操作似乎需要过滤 set 的输出——这是一种更加随意的方法。
Is there a Right Way?
有正确的方法吗?
回答by Kevin Little
$ declare -F
declare -f ::
declare -f _get_longopts
declare -f _longopts_func
declare -f _onexit
...
So, Jed Daniel's alias,
所以,杰德丹尼尔的别名,
declare -F | cut -d" " -f3
cuts on a space and echos the 3rd field:
切入一个空间并与第三个字段相呼应:
$ declare -F | cut -d" " -f3
::
_get_longopts
_longopts_func
_onexit
回答by Jed Daniels
I have an entry in my .bashrcthat says:
我有一个条目.bashrc说:
alias list='declare -F |cut -d" " -f3'
Which allows me to type listand get a list of functions. When I added it, I probably understood what was happening, but I can't remember to save my life at the moment.
这允许我输入list并获取函数列表。当我添加它时,我可能明白发生了什么,但我现在不记得挽救我的生命。
Good luck,
祝你好运,
--jed
--杰德
回答by Isaac
This has no issues with IFS nor globbing:
这对 IFS 或 globbing 都没有问题:
readarray -t funcs < <(declare -F)
printf '%s\n' "${funcs[@]##* }"
Of course, that needs bash 4.0.
当然,这需要 bash 4.0。
For bash since 2.04 use (a little trickier but equivalent):
对于 bash 自 2.04 使用(有点棘手但等效):
IFS=$'\n' read -d '' -a funcs < <(declare -F)
If you need that the exit code of this option is zero, use this:
如果您需要此选项的退出代码为零,请使用以下命令:
IFS=$'\n' read -d '' -a funcs < <( declare -F && printf 'saveIFS="$IFS"
IFS=$'\n'
funcs=($(declare -F)) # create an array
IFS="$saveIFS"
funcs=(${funcs[@]##* }) # keep only what's after the last space
' )
It will exit unsuccesful (not 0) if either declareor readfail. (Thanks to @CharlesDuffy)
如果declare或read失败,它将退出不成功(不是 0)。(感谢@CharlesDuffy)
回答by Paused until further notice.
Pure Bash:
纯重击:
$ for i in ${funcs[@]}; do echo "$i"; done
__ack_filedir
__gvfs_multiple_uris
_a2dismod
. . .
$ echo ${funcs[42]}
_command
Then, run at the Bash prompt as an example displaying bash-completion functions:
然后,在 Bash 提示符下运行,作为显示 bash 完成功能的示例:
set \
| egrep '^[^[:space:]]+ [(][)][[:space:]]*$' \
| sed -r -e 's/ [(][)][[:space:]]*$//'
回答by Charles Duffy
One (ugly) approach is to grep through the output of set:
一种(丑陋的)方法是通过 set 的输出进行 grep:
declare -F
Better approaches would be welcome.
更好的方法将受到欢迎。
回答by Juliano
Use the declare builtin to list currently defined functions:
使用 declare 内置函数列出当前定义的函数:
functions=$(for c in $patterns; do compgen -A function | grep "^$c$")
回答by Hai Vu
Perhaps my solution for this thread will work for you. Google for "get a list of function names in a shell script site:stackoverflow.com"
也许我对这个线程的解决方案对你有用。谷歌搜索“获取 shell 脚本站点中的函数名称列表:stackoverflow.com”
回答by FutureNerd
This collects a list of function names matching any of a list of patterns:
这将收集与任何模式列表匹配的函数名称列表:
which() {
for c in "$@"; do
compgen -A function |grep "^$c$" | while read line; do
echo "shell function $line" 1>&2
done
/usr/bin/which "$c"
done
}
The grep limits the output to only exact matches for the patterns.
grep 将输出限制为仅与模式完全匹配。
Check out the bash command typeas a better alternative to the following. Thanks to Charles Duffy for the clue.
查看 bash 命令类型作为以下更好的替代方法。感谢查尔斯·达菲提供线索。
The following uses that to answer the title question for humans rather than shell scripts: it adds a list of function names matching the given patterns, to the regular whichlist of shell scripts, to answer, "What code runs when I type a command?"
下面使用它来回答人类而不是 shell 脚本的标题问题:它将与给定模式匹配的函数名称列表添加到whichshell 脚本的常规列表中,以回答“当我键入命令时运行什么代码?”
(xkcd)Sandy$ which deactivate
shell function deactivate
(xkcd)Sandy$ which ls
/bin/ls
(xkcd)Sandy$ which .\*run_hook
shell function virtualenvwrapper_run_hook
So,
所以,
#!/bin/bash
# list-defined-functions.sh
# Lists functions defined in this script.
#
# Using `compgen -A function`,
# We can save the list of functions defined before running out script,
# the compare that to a new list at the end,
# resulting in the list of newly added functions.
#
# Usage:
# bash list-defined-functions.sh # Run in new shell with no predefined functions
# list-defined-functions.sh # Run in current shell with plenty of predefined functions
#
# Example predefined function
foo() { echo 'y'; }
# Retain original function list
# If this script is run a second time, keep the list from last time
[[ $original_function_list ]] || original_function_list=$(compgen -A function)
# Create some new functions...
myfunc() { echo "myfunc is the best func"; }
function another_func() { echo "another_func is better"; }
function superfunction { echo "hey another way to define functions"; }
# ...
# function goo() { echo ok; }
[[ $new_function_list ]] || new_function_list=$(comm -13 \
<(echo $original_function_list) \
<(compgen -A function))
echo "Original functions were:"
echo "$original_function_list"
echo
echo "New Functions defined in this script:"
echo "$new_function_list"
This is arguably a violation of the Unix "do one thing" philosophy, but I've more than once been desperate because whichwasn't finding a command that some package was supposed to contain, me forgetting about shell functions, so I've put this in my .profile.
这可以说是对 Unix“做一件事”哲学的违反,但我不止一次绝望,因为which没有找到某个包应该包含的命令,我忘记了 shell 函数,所以我把这在我的 .profile 中。

