В настоящее время я делаю некоторые модульные тесты, которые выполняются из Bash. Модульные тесты инициализируются, выполняются и очищаются в bash-скрипте. Этот скрипт обычно содержит функции init (), execute () и cleanup (). Но они не обязательны. Я хотел бы проверить, если они определены или не определены.
Раньше я делал это с помощью поиска и подмены источника, но это казалось неправильным. Есть ли более элегантный способ сделать это?
Изменить: следующий фрагмент работает как шарм:
fn_exists()
{
LC_ALL=C type $1 | grep -q 'shell function'
}
fn_exists foo || foo() { :; }
type -t
и==
.type test_function
говоритtest_function on funktio.
при использовании финского языка иist eine Funktion
при использовании немецкого языка.LC_ALL=C
вОтветы:
Я думаю, что вы ищете команду типа. Он скажет вам, является ли что-то функцией, встроенной функцией, внешней командой или просто не определено. Пример:
источник
type -t $function
это билет на еду.type [-t]
приятно рассказать вам, что это такое, но при тестировании, если что-то является функцией, это происходит медленно, так как вам приходится передавать по конвейеру grep или использовать обратные пометки, которые порождают подпроцесс.type -t realpath > /dev/shm/tmpfile ; read < /dev/shm/tmpfile
(плохой пример). Однако, объявлять является лучшим ответом, так как он имеет 0 дисков io.источник
type -t
, вы можете положиться на статус выхода вместо этого. Я давно привыкtype program_name > /dev/null 2>&1 && program_name arguments || echo "error"
видеть, смогу ли я позвонить. Очевидно,type -t
что метод выше и выше также позволяет определять тип, а не только то, является ли он «вызываемым».Если объявить в 10 раз быстрее, чем тест, это будет очевидным ответом.
Изменить: ниже,
-f
опция с BASH излишня, не стесняйтесь опускать ее. Лично у меня проблемы с запоминанием того, какая опция делает, поэтому я просто использую оба. -f показывает функции, а -F показывает имена функций.Параметр «-F» для объявления заставляет его возвращать только имя найденной функции, а не все содержимое.
Не должно быть никакого измеримого снижения производительности при использовании / dev / null, и если это вас так сильно беспокоит:
Или объедините их для собственного бессмысленного удовольствия. Они оба работают.
источник
-F
Вариант дез не существует в Zsh (полезно для переносимости)-F
на самом деле также не является необходимым: кажется, он подавляет только определение функции / тело.cat "$fn" | wc -c
? Что касается zsh, то, если тег bash не подскажет вам, возможно, сам вопрос должен возникнуть. Msgstr "Определить, существует ли функция в bash". Я также хотел бы отметить, что, хотя-F
опция не существует в zsh, она также не вызывает ошибку, поэтому использование как -f, так и -F позволяет выполнить проверку как в zsh, так и в bash, что в противном случае не будет ,-F
используется в zsh для чисел с плавающей запятой. Я не могу понять, почему использование-F
делает его лучше в Bash ?! У меня сложилось впечатление, чтоdeclare -f
в bash работает то же самое (относительно кода возврата).Заимствуя из других решений и комментариев, я придумал это:
Используется в качестве ...
Он проверяет, является ли данный аргумент функцией, и избегает перенаправлений и других операций поиска.
источник
[ $(type -t "$1")"" == 'function' ]
[[...]]
вместо[...]
и избавиться от взлома цитаты. Также разветвление backticks, которое является медленным. Используйтеdeclare -f $1 > /dev/null
вместо этого.fn_exists() { [ x$(type -t $1) = xfunction ]; }
Выискивая старый пост ... но я недавно использовал это и проверил обе альтернативы, описанные с помощью:
это породило:
объявляю это чертовски быстрее!
источник
test_type_nogrep () { a () { echo 'a' ;}; local b=$(type a); c=${b//is a function/}; [ $? = 0 ] && return 1 || return 0; }
type
иdeclare
. Это сравниваетсяtype | grep
сdeclare
. Это большая разница.Это сводится к тому, чтобы использовать 'Declare' для проверки кода выхода или выхода.
Стиль вывода:
Использование:
Однако, если память служит, перенаправление на ноль происходит быстрее, чем подстановка вывода (если говорить о том, что ужасный и устаревший метод `cmd` должен быть изгнан и вместо него должен использоваться $ (cmd).) И так как метод Declare возвращает true / false, если найден / не найден, и функции возвращают код завершения последней команды в функции, поэтому явный возврат обычно не требуется, и поскольку проверка кода ошибки выполняется быстрее, чем проверка строкового значения (даже пустой строки):
Стиль выхода из статуса:
Это, вероятно, примерно так кратко и мягко, как вы можете получить.
источник
isFunction() { declare -F "$1"; } >&-
isFunction() { declare -F -- "$@" >/dev/null; }
моя рекомендация Он также работает со списком имен (успешно, только если все являются функциями), не создает проблем с именами, начинающимися с,-
и, с моей стороны (bash
4.2.25),declare
всегда завершается ошибкой при закрытии вывода>&-
, поскольку не может записать имя в этом случаеecho
иногда может произойти сбой с «прерванным системным вызовом» на некоторых платформах. В этом случае «проверить && эхо да || эхо нет» по- прежнему может выводить ,no
еслиcheck
это правда.Тестирование разных решений:
выходы, например:
Так что,
declare -F f
похоже, лучшее решение.источник
declare -F f
не возвращает ненулевое значение, если f не существует в zsh, но bash yes. Будьте осторожны, используя его.declare -f f
с другой стороны, работает как положено, добавляя определение функции на стандартный вывод (что может раздражать ...)test_type3 () { [[ $(type -t f) = function ]] ; }
есть предельные затраты на определение локальной переменной (хотя <10%)Из моего комментария к другому ответу (который я постоянно пропускаю, когда возвращаюсь на эту страницу)
источник
Обновить
источник
Я бы улучшил это до:
И используйте это так:
источник
Это говорит вам, если он существует, но не то, что это функция
источник
Мне особенно понравилось решение от Грегори Жозефа
Но я немного изменил его, чтобы преодолеть "двойную кавычку":
источник
Можно использовать 'type' без каких-либо внешних команд, но вы должны вызывать его дважды, так что он все равно заканчивается примерно вдвое медленнее, чем версия 'Declare':
Плюс это не работает в POSIX sh, так что это абсолютно бесполезно, кроме как мелочи!
источник