Ответ 1
if type __git_ps1 | grep -q '^function$' 2>/dev/null; then
PS1=whatever
fi
Как определить, определена ли функция в bash script?
Я пытаюсь сделать мой .bash_login script переносимым между системами, поэтому я хочу добавить логику только для вызова функции, если она существует.
Я хочу добавить __git_ps1()
в PS1
только в том случае, если эта функция существует в этой системе. Эта функция обычно определяется в git-completion.bash
, которая поставляется с источником git или одним из сценариев завершения bash, которые устанавливаются в port/apt.
if type __git_ps1 | grep -q '^function$' 2>/dev/null; then
PS1=whatever
fi
Я понимаю, что это старый вопрос, но ни один из других ответов не делает это так просто, как хотелось бы. Это использует type -t
(как предложено в комментарии Чена Леви) как эффективный тип теста, но затем использует сравнение строк оболочки, а не вызывает grep.
if [ "$(type -t somefunc)" = 'function' ]; then
somefunc arg1 arg2
fi
И чтобы сделать это еще дальше, он также работает косвенно:
funcname=do_it_special_$somehow
if [ "$(type -t $funcname)" != 'function' ]; then
funcname=do_it_normal
fi
$funcname arg1 arg2
Вы можете сделать это, используя:
type function_name
in вернет ваше определение функции в том случае, если оно существует. Таким образом, вы можете проверить, когда вывод пуст или нет.
PS. Еще лучше, что я только что проверил, будет выводиться эта функция, которая не существует в противном случае для тела выходной функции.
Если вам нужна версия, совместимая с /bin/sh
, вы не можете использовать typeset
или declare
для проверки определения функции, поскольку она не является встроенной оболочкой. Кроме того, опция -f
для type
может быть недоступна в некоторых системах.
Решение, которое я представляю, частично описано в других ответах:
isFunction() {
type $1 | head -1 | egrep "^$1.*function\$" >/dev/null 2>&1;
return;
}
isFunction __git_ps1 && PS1=__git_ps1
declare -F 'function_name' > /dev/null
echo $?
$? результат имеет значение 0, если функция существует, 1 в противном случае
Я думаю, что лучше использовать declare, даже если он немного медленнее, чем тип. Тип также подходит для псевдонимов или скриптов, которые находятся в PATH.
Я использую это:
function function_exists
{
FUNCTION_NAME=$1
[ -z "$FUNCTION_NAME" ] && return 1
declare -F "$FUNCTION_NAME" > /dev/null 2>&1
return $?
}
Так что позже в моих сценариях я легко вижу, что происходит:
if function_exists __git_ps1
then
PS1=__git_ps1
fi
Или даже неподвижный однострочный слой:
function_exists __git_ps1 && PS1=__git_ps1
Вы можете перечислить все доступные функции или проверить отдельные функции с помощью compgen:
help compgen
compgen -A function
compgen -A function myfunc 1>/dev/null && echo 'myfunc already exists' || exit 1
if declare -F | grep __git_ps1$
then
PS1=whatever
fi
Примечание. busybox (минимализм в одной реализации оболочки, полезный для Windows, например) имеет тип "type", но "type -t" печатает неправильную вещь, поэтому я просто проверяю возвращаемое значение типа, чтобы узнать, можно ли что-то вызвать, busybox также не объявляет.