Obecnie przeprowadzam kilka testów jednostkowych wykonywanych z poziomu bash. Testy jednostkowe są inicjowane, wykonywane i czyszczone w skrypcie bash. Ten skrypt zwykle zawiera funkcje init (), execute () i cleanup (). Ale nie są obowiązkowe. Chciałbym sprawdzić, czy są, czy nie są zdefiniowane.
Zrobiłem to wcześniej, szukając źródła i szukając źródła, ale wydawało się to złe. Czy jest na to bardziej elegancki sposób?
Edycja: Poniższy fragment kodu działa jak urok:
fn_exists()
{
LC_ALL=C type $1 | grep -q 'shell function'
}
fn_exists foo || foo() { :; }
type -t
i==
.type test_function
mówitest_function on funktio.
podczas korzystania z fińskich ustawień regionalnych iist eine Funktion
podczas używania języka niemieckiego.LC_ALL=C
do resqueOdpowiedzi:
Myślę, że szukasz polecenia „typ”. Powie ci, czy coś jest funkcją, funkcją wbudowaną, poleceniem zewnętrznym, czy po prostu nie jest zdefiniowane. Przykład:
źródło
type -t $function
jest bilet na posiłek.type [-t]
miło jest powiedzieć ci, co to jest, ale podczas testowania, czy coś jest funkcją, jest powolne, ponieważ musisz potokować, aby grep lub użyć backicks, z których oba odradzają podproces.type -t realpath > /dev/shm/tmpfile ; read < /dev/shm/tmpfile
(Zły przykład). Jednak deklaracja jest najlepszą odpowiedzią, ponieważ ma 0 dysków io.źródło
type -t
, możesz zamiast tego polegać na statusie wyjścia. Dawno jużtype program_name > /dev/null 2>&1 && program_name arguments || echo "error"
widziałem, czy będę w stanie zadzwonić. Oczywiścietype -t
powyższa metoda pozwala również wykryć typ, nie tylko to, czy można go „wywołać”.Jeśli deklaracja jest 10 razy szybsza niż test, wydaje się to oczywistą odpowiedzią.
Edycja: poniżej
-f
opcja jest zbędna w przypadku BASH, możesz ją pominąć. Osobiście mam problem z zapamiętaniem, która opcja to robi, więc używam obu. -f pokazuje funkcje, a -F pokazuje nazwy funkcji.Opcja „-F” do zadeklarowania powoduje, że zwraca tylko nazwę znalezionej funkcji, a nie całą zawartość.
Nie powinno być żadnych wymiernych ograniczeń wydajności za używanie / dev / null, a jeśli tak bardzo cię to martwi:
Lub połącz te dwa elementy, aby uzyskać własną bezcelową przyjemność. Oboje działają.
źródło
-F
Opcja des nie istnieje w zsh (przydatne do przenoszenia)-F
też nie jest tak naprawdę konieczne: wydaje się, że tłumi ono jedynie definicję / treść funkcji.cat "$fn" | wc -c
? Jeśli chodzi o zsh, jeśli tag bash cię nie podpowie, być może samo pytanie powinno mieć. „Sprawdź, czy funkcja istnieje w bash”. Chciałbym ponadto zauważyć, że chociaż-F
opcja nie istnieje w Zsh, nie powoduje również błędu, dlatego użycie zarówno -f, jak i -F pozwala na pomyślne sprawdzenie zarówno w Zsh, jak i bash, co inaczej nie byłoby .-F
jest używany w zsh dla liczb zmiennoprzecinkowych. Nie rozumiem, dlaczego używanie-F
poprawia jakość bash ?! Mam wrażenie, żedeclare -f
działa tak samo w bash (w odniesieniu do kodu powrotu).Pożyczając od innych rozwiązań i komentarzy, wymyśliłem to:
Użyty jako ...
Sprawdza, czy dany argument jest funkcją i unika przekierowań i innych greppingów.
źródło
[ $(type -t "$1")"" == 'function' ]
[[...]]
zamiast[...]
i pozbywaj się hacków z wyceną. Również widelec wsteczny, który jest wolny. Użyjdeclare -f $1 > /dev/null
zamiast tego.fn_exists() { [ x$(type -t $1) = xfunction ]; }
Pogłębiam stary post ... ale ostatnio z niego skorzystałem i przetestowałem obie alternatywy opisane za pomocą:
to wygenerowało:
deklaruj, że jest helluvalot szybciej!
źródło
test_type_nogrep () { a () { echo 'a' ;}; local b=$(type a); c=${b//is a function/}; [ $? = 0 ] && return 1 || return 0; }
type
ideclare
. Porównuje siętype | grep
zdeclare
. To duża różnica.Sprowadza się do użycia polecenia „deklaruj” do sprawdzenia kodu wyjściowego lub kodu zakończenia.
Styl wyjściowy:
Stosowanie:
Jeśli jednak pamięć służy, przekierowanie na wartość NULL jest szybsze niż podstawianie danych wyjściowych (mówiąc o tym, że okropna i przestarzała metoda `cmd` powinna zostać usunięta, a zamiast niej należy użyć $ (cmd).) A ponieważ deklaracja zwraca true / false, jeśli znaleziono / nie znaleziono, a funkcje zwracają kod wyjścia ostatniego polecenia w funkcji, więc jawny zwrot zwykle nie jest konieczny, a ponieważ sprawdzenie kodu błędu jest szybsze niż sprawdzenie wartości ciągu (nawet ciągu zerowego):
Styl statusu wyjścia:
To prawdopodobnie tak zwięzłe i łagodne, jak to tylko możliwe.
źródło
isFunction() { declare -F "$1"; } >&-
isFunction() { declare -F -- "$@" >/dev/null; }
to moja rekomendacja. Działa również na liście nazw (udaje się tylko wtedy, gdy wszystkie są funkcjami), nie daje problemów z nazwami zaczynającymi się od,-
a po mojej stronie (bash
4.2.25)declare
zawsze kończy się niepowodzeniem, gdy wyjście jest zamknięte>&-
, ponieważ nie może zapisać nazwy na standardowe wyjście w tej sprawieecho
czasami może się nie powieść z „przerwanym wywołaniem systemowym” na niektórych platformach. W takim przypadku „check && echo yes || echo no” nadal może wyświetlać,no
jeślicheck
jest to prawda.Testowanie różnych rozwiązań:
dane wyjściowe np .:
Więc
declare -F f
wydaje się być najlepszym rozwiązaniem.źródło
declare -F f
nie zwraca niezerowej wartości, jeśli f nie istnieje na zsh, ale bash tak. Ostrożnie go używaj.declare -f f
, z drugiej strony, działa zgodnie z oczekiwaniami, dołączając definicję funkcji na stdout (co może być denerwujące ...)test_type3 () { [[ $(type -t f) = function ]] ; }
istnieje marginalny koszt zdefiniowania lokalnego var (chociaż <10%)Z mojego komentarza do innej odpowiedzi (której brakuje mi, gdy wracam na tę stronę)
źródło
aktualizacja
źródło
Poprawiłbym to, aby:
I użyj tego w ten sposób:
źródło
To mówi ci, jeśli istnieje, ale nie, że jest to funkcja
źródło
Szczególnie podobało mi się rozwiązanie Grégory Joseph
Ale zmodyfikowałem to trochę, aby pokonać „podwójny cytat brzydkiej sztuczki”:
źródło
Możliwe jest użycie „type” bez żadnych zewnętrznych poleceń, ale musisz wywołać go dwa razy, więc nadal kończy się to około dwa razy wolniej niż wersja „deklaruj”:
Plus to nie działa w POSIX sh, więc jest całkowicie bezwartościowe, z wyjątkiem ciekawostek!
źródło