Derzeit mache ich einige Unit-Tests, die von Bash ausgeführt werden. Unit-Tests werden in einem Bash-Skript initialisiert, ausgeführt und bereinigt. Dieses Skript enthält normalerweise die Funktionen init (), execute () und cleanup (). Sie sind jedoch nicht obligatorisch. Ich möchte testen, ob sie definiert sind oder nicht.
Ich habe dies zuvor getan, indem ich die Quelle ergriffen und ausgesät habe, aber es schien falsch zu sein. Gibt es eine elegantere Möglichkeit, dies zu tun?
Bearbeiten: Das folgende Sniplet wirkt wie ein Zauber:
fn_exists()
{
LC_ALL=C type $1 | grep -q 'shell function'
}
fn_exists foo || foo() { :; }
type -t
und speichern==
.type test_function
sagttest_function on funktio.
bei Verwendung des finnischen Gebietsschemas undist eine Funktion
bei Verwendung des deutschen.LC_ALL=C
zum ResqueAntworten:
Ich denke, Sie suchen nach dem Befehl 'type'. Hier erfahren Sie, ob etwas eine Funktion, eine integrierte Funktion, ein externer Befehl ist oder nicht. Beispiel:
quelle
type -t $function
ist die Essenskarte.type [-t]
Es ist schön, Ihnen zu sagen , was eine Sache ist, aber wenn Sie testen, ob etwas eine Funktion ist, ist es langsam, da Sie Pipe zu Grep oder Backticks verwenden müssen, die beide einen Unterprozess erzeugen.type -t realpath > /dev/shm/tmpfile ; read < /dev/shm/tmpfile
(schlechtes Beispiel). Allerdings declare ist die beste Antwort , da 0 Disk io ist hat.quelle
type -t
, Sie können sich stattdessen auf den Exit-Status verlassen. Ich habe lange nachgesehentype program_name > /dev/null 2>&1 && program_name arguments || echo "error"
, ob ich etwas anrufen kann. Offensichtlichtype -t
erlaubt die und die obige Methode auch, den Typ zu erkennen, nicht nur, ob er "aufrufbar" ist.Wenn deklarieren 10x schneller als Test ist, scheint dies die offensichtliche Antwort zu sein.
Bearbeiten: Unten ist die
-f
Option mit BASH überflüssig. Sie können sie auch weglassen. Persönlich fällt es mir schwer, mich daran zu erinnern, welche Option welche macht, also benutze ich einfach beide. -f zeigt Funktionen und -F zeigt Funktionsnamen.Die zu deklarierende Option "-F" gibt nur den Namen der gefundenen Funktion und nicht den gesamten Inhalt zurück.
Es sollte keine messbare Leistungseinbuße für die Verwendung von / dev / null geben, und wenn es Sie so sehr beunruhigt:
Oder kombinieren Sie beides für Ihren eigenen sinnlosen Genuss. Sie arbeiten beide.
quelle
-F
Option des existiert nicht in zsh (nützlich für die Portabilität)-F
auch ist eigentlich nicht nötig: es scheint nur die funktionsdefinition / body zu unterdrücken.cat "$fn" | wc -c
? Was zsh betrifft, wenn das Bash- Tag Sie nicht darauf hingewiesen hat, sollte es vielleicht die Frage selbst geben. "Bestimmen Sie, ob eine Funktion in bash vorhanden ist". Ich möchte weiter darauf hinweisen, dass die-F
Option zwar nicht in zsh vorhanden ist, aber auch keinen Fehler verursacht. Daher ermöglicht die Verwendung von -f und -F, dass die Prüfung sowohl in zsh als auch in bash erfolgreich ist, was sonst nicht der Fall wäre .-F
wird in zsh für Gleitkommazahlen verwendet. Ich kann nicht verstehen, warum die Verwendung-F
in Bash besser ist?! Ich habe den Eindruck, dass esdeclare -f
in Bash genauso funktioniert (in Bezug auf den Rückkehrcode).In Anlehnung an andere Lösungen und Kommentare habe ich Folgendes gefunden:
Benutzt als ...
Es prüft, ob das angegebene Argument eine Funktion ist, und vermeidet Umleitungen und andere Grepping.
quelle
[ $(type -t "$1")"" == 'function' ]
[[...]]
statt[...]
und zitieren den Zitat-Hack. Auch Backticks Gabel, die langsam ist. Verwenden Siedeclare -f $1 > /dev/null
stattdessen.fn_exists() { [ x$(type -t $1) = xfunction ]; }
Einen alten Beitrag ausgraben ... aber ich habe ihn kürzlich genutzt und beide Alternativen getestet, die beschrieben wurden mit:
dies erzeugte:
deklarieren ist ein helluvalot schneller!
quelle
test_type_nogrep () { a () { echo 'a' ;}; local b=$(type a); c=${b//is a function/}; [ $? = 0 ] && return 1 || return 0; }
type
unddeclare
. Es ist vergleichbartype | grep
mitdeclare
. Das ist ein großer Unterschied.Es läuft darauf hinaus, 'declare' zu verwenden, um entweder den Ausgabe- oder den Exit-Code zu überprüfen.
Ausgabestil:
Verwendung:
Wenn jedoch Speicher bereitgestellt wird, ist die Umleitung auf Null schneller als die Ersetzung der Ausgabe (wenn man davon spricht, sollte die schreckliche und veraltete "cmd" -Methode verbannt und stattdessen $ (cmd) verwendet werden.) Und da declare true / false zurückgibt, wenn gefunden / nicht gefunden, und Funktionen geben den Exit-Code des letzten Befehls in der Funktion zurück, sodass eine explizite Rückgabe normalerweise nicht erforderlich ist. Da das Überprüfen des Fehlercodes schneller ist als das Überprüfen eines Zeichenfolgenwerts (sogar einer Nullzeichenfolge):
Statusstatus beenden:
Das ist wahrscheinlich so prägnant und harmlos wie möglich.
quelle
isFunction() { declare -F "$1"; } >&-
isFunction() { declare -F -- "$@" >/dev/null; }
ist meine Empfehlung. Es funktioniert auch mit einer Liste von Namen (erfolgreich nur, wenn alle Funktionen sind), gibt keine Probleme mit Namen, die mit beginnen,-
und schlägt an meiner Seite (bash
4.2.25)declare
immer fehl, wenn die Ausgabe mit geschlossen wird>&-
, weil es den Namen nicht schreiben kann in diesem Fall zu stdoutecho
dies auf einigen Plattformen manchmal mit einem "unterbrochenen Systemaufruf" fehlschlagen kann. In diesem Fall kann "check && echo yes || echo no" weiterhin ausgegeben werden,no
wenn dies dercheck
Fall ist.Testen verschiedener Lösungen:
Ausgänge zB:
Also
declare -F f
scheint die beste Lösung zu sein.quelle
declare -F f
Gibt keinen Wert ungleich Null zurück, wenn f auf zsh nicht existiert, aber bash yes. Sei vorsichtig damit.declare -f f
funktioniert andererseits wie erwartet, indem die Definition der Funktion an den Standard angehängt wird (was ärgerlich sein kann ...)test_type3 () { [[ $(type -t f) = function ]] ; }
es gibt Grenzkosten für die Definition einer lokalen Var (obwohl <10%)Aus meinem Kommentar zu einer anderen Antwort (die ich immer wieder vermisse, wenn ich auf diese Seite zurückkomme)
quelle
aktualisieren
quelle
Ich würde es verbessern, um:
Und benutze es so:
quelle
Dies sagt Ihnen, ob es existiert, aber nicht, dass es eine Funktion ist
quelle
Besonders gut hat mir die Lösung von Grégory Joseph gefallen
Aber ich habe es ein wenig modifiziert, um den "hässlichen Trick mit doppelten Anführungszeichen" zu überwinden:
quelle
Es ist möglich, 'type' ohne externe Befehle zu verwenden, aber Sie müssen es zweimal aufrufen, damit es immer noch etwa doppelt so langsam ist wie die 'declare'-Version:
Außerdem funktioniert dies in POSIX sh nicht, so dass es völlig wertlos ist, außer als Trivia!
quelle