Перечисление определенных функций в Bash - PullRequest
16 голосов
/ 13 апреля 2010

Я пытаюсь написать некоторый код на bash, который использует самоанализ для выбора соответствующей функции для вызова.

Для определения кандидатов необходимо знать, какие функции определены. Легко перечислить определенные переменные в bash, используя только расширение параметра:

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

Однако выполнение этого для функций , по-видимому, требует фильтрации выходных данных set - гораздо более случайный подход.

Есть ли верный путь?

Ответы [ 10 ]

28 голосов
/ 13 апреля 2010

Как насчет compgen :

compgen -A function   # compgen is a shell builtin
7 голосов
/ 13 апреля 2010
$ declare -F
declare -f ::
declare -f _get_longopts
declare -f _longopts_func
declare -f _onexit
...

Итак, псевдоним Джеда Даниэля,

declare -F | cut -d" " -f3

разрезает пробел и повторяет 3-е поле:

$ declare -F | cut -d" " -f3
::
_get_longopts
_longopts_func
_onexit
5 голосов
/ 13 апреля 2010

У меня есть запись в моем .bashrc, которая гласит:

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

, которая позволяет мне набрать list и получить список функций.Когда я добавил это, я, вероятно, понял, что происходит, но я не могу вспомнить, как спасти свою жизнь в данный момент.

2 голосов
/ 09 ноября 2016

Это не имеет никаких проблем с IFS и глобализацией:

readarray -t funcs < <(declare -F)

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

Конечно, для этого нужен bash 4.0.

Для bash начиная с 2.04 (немного сложнее, но эквивалентно):

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

Если вам нужно, чтобы код выхода этой опции был равен нулю, используйте это:

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

Он завершится неудачно (не 0), если declare или read не удастся. (Спасибо @ CharlesDuffy )

1 голос
/ 13 апреля 2010

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:

$ for i in ${funcs[@]}; do echo "$i"; done
__ack_filedir
__gvfs_multiple_uris
_a2dismod
. . .
$ echo ${funcs[42]}
_command
1 голос
/ 13 апреля 2010

Используйте встроенную функцию объявляемого для отображения текущих определенных функций:

declare -F
1 голос
/ 13 апреля 2010

Один (некрасивый) подход состоит в том, чтобы просмотреть результаты набора:

set \
  | egrep '^[^[:space:]]+ [(][)][[:space:]]*$' \
  | sed -r -e 's/ [(][)][[:space:]]*$//'

Лучшие подходы приветствуются.

0 голосов
/ 29 августа 2014
#!/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"
0 голосов
/ 29 сентября 2013

Собирает список имен функций, соответствующих любому из списка шаблонов:

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

grep ограничивает вывод только точными совпадениями для шаблонов.

Проверьте команду bash type как лучшую альтернативу следующему. Спасибо Чарльзу Даффи за подсказку.

Следующее использует это для ответа на вопрос о названии для людей, а не для сценариев оболочки: оно добавляет список имен функций, соответствующих заданным шаблонам, в обычный список which сценариев оболочки, чтобы ответить: «Какой код выполняется, когда Я набираю команду? "

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 не нашел команду, которую должен был содержать какой-либо пакет, я забыл о функциях оболочки Я поместил это в свой .profile.

0 голосов
/ 16 апреля 2010

Возможно, мое решение для этой темы подойдет вам. Google для "получить список имен функций на сайте сценария оболочки: stackoverflow.com"

получить список имен функций в сценарии оболочки

...