在Bash中列出已定义的函数

时间:2010-04-12 22:03:33

标签: bash introspection

我正在尝试在bash中编写一些代码,它使用内省来选择要调用的相应函数。

确定候选者需要知道定义了哪些功能。只使用参数扩展在bash中列出已定义的变量很容易:

$ prefix_foo="one"
$ prefix_bar="two"
$ echo "${!prefix_*}"
prefix_bar prefix_foo

然而,为函数执行此操作似乎需要过滤set的输出 - 这是一种更随意的方法。

有正确的方法吗?

11 个答案:

答案 0 :(得分:28)

compgen

怎么样?
compgen -A function   # compgen is a shell builtin

答案 1 :(得分:7)

$ declare -F
declare -f ::
declare -f _get_longopts
declare -f _longopts_func
declare -f _onexit
...

所以,Jed Daniels别名,

declare -F | cut -d" " -f3

削减空间并回显第3个字段:

$ declare -F | cut -d" " -f3
::
_get_longopts
_longopts_func
_onexit

答案 2 :(得分:5)

我的.bashrc中有一个条目:

alias list='declare -F |cut -d" " -f3'

允许我输入list并获取功能列表。当我添加它时,我可能已经理解发生了什么,但我现在不记得挽救我的生命。

祝你好运,

- JED

答案 3 :(得分:2)

这与IFS没有问题也没有问题:

readarray -t funcs < <(declare -F)

printf '%s\n' "${funcs[@]##* }"

当然,这需要bash 4.0。

对于自2.04使用以来的bash(有点棘手但等效):

IFS=$'\n' read -d '' -a funcs < <(declare -F)

如果您需要此选项的退出代码为零,请使用:

IFS=$'\n' read -d '' -a funcs < <( declare -F && printf '\0' )

如果declareread失败,它将退出unsuccesful(而不是0)。 (感谢 @CharlesDuffy

答案 4 :(得分:1)

一种(丑陋的)方法是通过set:

的输出进行grep
set \
  | egrep '^[^[:space:]]+ [(][)][[:space:]]*$' \
  | sed -r -e 's/ [(][)][[:space:]]*$//'

欢迎更好的方法。

答案 5 :(得分:1)

使用declare builtin列出当前定义的函数:

declare -F

答案 6 :(得分:1)

Pure Bash:

saveIFS="$IFS"
IFS=$'\n'
funcs=($(declare -F))      # create an array
IFS="$saveIFS"
funcs=(${funcs[@]##* })    # keep only what's after the last space

然后,以Bash提示符运行,作为显示bash-completion函数的示例:

$ for i in ${funcs[@]}; do echo "$i"; done
__ack_filedir
__gvfs_multiple_uris
_a2dismod
. . .
$ echo ${funcs[42]}
_command

答案 7 :(得分:1)

zsh 仅(不是要求的内容,但所有更通用的问题都已作为此副本的副本关闭):

typeset -f +

来自man zshbuiltins

-f     The  names  refer  to functions rather than parameters.
 +     If `+' appears by itself in a separate word as the last
       option, then the names of all parameters (functions with -f)
       are printed, but  the values  (function  bodies)  are not.

示例:

martin@martin ~ % cat test.zsh 
#!/bin/zsh

foobar()
{
  echo foobar
}

barfoo()
{
  echo barfoo
}

typeset -f +

输出:

martin@martin ~ % ./test.zsh
barfoo
foobar

答案 8 :(得分:0)

也许我对此主题的解决方案对您有用。谷歌“获取shell脚本站点中的函数名列表:stackoverflow.com”

get a list of function names in a shell script

答案 9 :(得分:0)

这将收集与任何模式列表匹配的函数名称列表:

functions=$(for c in $patterns; do compgen -A function | grep "^$c\$")

grep将输出限制为仅与模式完全匹配。

查看bash命令type作为以下内容的更好替代方案。感谢Charles Duffy的线索。

以下用于回答人类而不是shell脚本的标题问题:它将与给定模式匹配的函数名称列表添加到常规which shell脚本列表中,以回答“什么代码我输入命令时会运行吗?“

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
 }

所以,

(xkcd)Sandy$ which deactivate
shell function deactivate
(xkcd)Sandy$ which ls
/bin/ls
(xkcd)Sandy$ which .\*run_hook
shell function virtualenvwrapper_run_hook

这可以说是违反Unix“做一件事”的哲学,但我不止一次绝望,因为which没有找到某个包应该包含的命令,我忘记了shell函数,所以我把它放在我的.profile中。

答案 10 :(得分:0)

#!/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"