Проверьте, существует ли функция из скрипта bash [дубликат]

18

Как определить, определена ли уже функция в скрипте bash?

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

Я хочу добавить __git_ps1() к PS1 , только если эта функция существует в этой системе. Эта функция обычно определяется в git-completion.bash , который поставляется с git source, или с помощью одного из сценариев завершения bash, которые устанавливает ports / apt.

    
задан csexton 17.06.2009 в 16:50
источник

9 ответов

10
if type __git_ps1 | grep -q '^function$' 2>/dev/null; then
    PS1=whatever
fi
    
ответ дан chaos 17.06.2009 в 17:00
  • Использование типа было намного быстрее, чем объявить - спасибо. –  csexton 22.06.2009 в 15:44
  • Это почти правильно, но оно также вернет «истину», если __get_ps1 является псевдонимом, встроенным и т. д. Используйте, если type -t имя_функции | grep -q "^ функция $"; затем ... fi, чтобы убедиться, что __git_ps1 является функцией. –  Chen Levy 05.04.2011 в 15:41
  • @ChenLevy: Отредактированный per. –  chaos 20.07.2012 в 05:51
  • Нет причин для grep; просто введите тип, который возвращает true / false, если тип существует или нет. И, действительно, не имеет значения, используете ли вы тип -t или нет; если (стандартная) __git_ps1 определена, то это, вероятно, то, что вы хотите использовать для своей PS1-подсказки, независимо от того, как она определена; то есть, если тип __git_ps1> / dev / null 2> & 1; то PS1 = '\ n \ w $ (__ git_ps1) \ n \! $'; фи –  michael 08.10.2012 в 12:05
14

Я понимаю, что это старый вопрос, но ни один из других ответов не делает это так просто, как мне бы хотелось. Это использует 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
    
ответ дан Trevor Robinson 14.09.2011 в 00:07
  • Мне действительно нравится это решение, хотя чувствую, что обратные шаги в строке чувствуют себя неловко. Несмотря на это, я обязательно буду использовать это. –  csexton 14.09.2011 в 04:05
  • @csexton Вы можете использовать «$ (type -t somefunc)» вместо обратных ссылок. –  wisbucky 14.03.2017 в 00:29
8

Вы можете сделать это, используя:

type function_name

in вернет вам определение функции, если оно существует. Таким образом, вы можете проверить всякий раз, когда вывод пуст или нет.

PS. Более того, я только что проверил, что будет выведено, что функция не существует, иначе выведите тело функции.

    
ответ дан Artem Barger 17.06.2009 в 17:00
6

Если вам нужна версия, соответствующая /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
    
ответ дан marcel 08.11.2011 в 12:55
4

объявить -F 'имя_функции' > / DEV / нуль

echo $?

$? результат имеет значение 0, если функция существует, 1 в противном случае

    
ответ дан Fritz G. Mehner 17.06.2009 в 17:02
2

Я думаю, что лучше использовать объявить, даже если это немного медленнее, чем тип. Также введите suceeds для псевдонимов или сценариев, которые находятся в 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
    
ответ дан Jacobo de Vera 28.07.2009 в 22:52
1

Вы можете перечислить все доступные функции или проверить отдельные функции с помощью compgen:

help compgen

compgen -A function

compgen -A function myfunc 1>/dev/null && echo 'myfunc already exists' || exit 1
    
ответ дан tim 05.04.2011 в 15:25
0
if declare -F | grep __git_ps1$
then
    PS1=whatever
fi
    
ответ дан Jaime Soriano 17.06.2009 в 17:11
0

Обратите внимание, у busybox (минималистская реализация всего в одной оболочке, полезная, например, для Windows) есть «type», но «type -t» печатает неправильную вещь, поэтому я просто проверяю возвращаемое значение типа, чтобы увидеть, может ли что-то вызываться , busybox также не имеет объявления.

    
ответ дан Reed Hedges 31.05.2012 в 18:30