Domanda

Attualmente sto eseguendo alcuni test unitari eseguiti da bash.Gli unit test vengono inizializzati, eseguiti e ripuliti in uno script bash.Questo script di solito contiene le funzioni init(),execute() e cleanup().Ma non sono obbligatori.Mi piacerebbe verificare se sono o non sono definiti.

L'ho fatto in precedenza greping e seding la fonte, ma sembrava sbagliato.Esiste un modo più elegante per farlo?

Modificare:Il seguente frammento funziona come un incantesimo:

fn_exists()
{
    LC_ALL=C type $1 | grep -q 'shell function'
}
È stato utile?

Soluzione

Penso che tu stia cercando il comando "tipo".Ti dirà se qualcosa è una funzione, una funzione incorporata, un comando esterno o semplicemente non definito.Esempio:

$ LC_ALL=C type foo
bash: type: foo: not found

$ LC_ALL=C type ls
ls is aliased to `ls --color=auto'

$ which type

$ LC_ALL=C type type
type is a shell builtin

$ LC_ALL=C type -t rvm
function

$ if [ -n "$(LC_ALL=C type -t rvm)" ] && [ "$(LC_ALL=C type -t rvm)" = function ]; then echo rvm is a function; else echo rvm is NOT a function; fi
rvm is a function

Altri suggerimenti

$ g() { return; }
$ declare -f g > /dev/null; echo $?
0
$ declare -f j > /dev/null; echo $?
1

Se la dichiarazione è 10 volte più veloce del test, questa sembrerebbe la risposta ovvia.

Modificare:Di seguito, il -f L'opzione è superflua con BASH, sentiti libero di lasciarla fuori.Personalmente, ho difficoltà a ricordare quale opzione fa quale, quindi le utilizzo entrambe. -F mostra le funzioni e -F mostra i nomi delle funzioni.

#!/bin/sh

function_exists() {
    declare -f -F $1 > /dev/null
    return $?
}

function_exists function_name && echo Exists || echo No such function

L'opzione "-F" da dichiarare fa sì che venga restituito solo il nome della funzione trovata, anziché l'intero contenuto.

Non dovrebbe esserci alcuna penalizzazione misurabile delle prestazioni per l'utilizzo di /dev/null e, se ti preoccupa così tanto:

fname=`declare -f -F $1`
[ -n "$fname" ]    && echo Declare -f says $fname exists || echo Declare -f says $1 does not exist

Oppure combina i due, per il tuo inutile divertimento.Funzionano entrambi.

fname=`declare -f -F $1`
errorlevel=$?
(( ! errorlevel )) && echo Errorlevel says $1 exists     || echo Errorlevel says $1 does not exist
[ -n "$fname" ]    && echo Declare -f says $fname exists || echo Declare -f says $1 does not exist

Prendendo in prestito da altre soluzioni e commenti, ho pensato a questo:

fn_exists() {
  # appended double quote is an ugly trick to make sure we do get a string -- if $1 is not a known command, type does not output anything
  [ `type -t $1`"" == 'function' ]
}

Usato come ...

if ! fn_exists $FN; then
    echo "Hey, $FN does not exist ! Duh."
    exit 2
fi

Controlla se l'argomento fornito è una funzione ed evita reindirizzamenti e altri grepping.

Ripasso un vecchio post...ma recentemente l'ho utilizzato e ho testato entrambe le alternative descritte con:

test_declare () {
    a () { echo 'a' ;}

    declare -f a > /dev/null
}

test_type () {
    a () { echo 'a' ;}
    type a | grep -q 'is a function'
}

echo 'declare'
time for i in $(seq 1 1000); do test_declare; done
echo 'type'
time for i in $(seq 1 100); do test_type; done

questo ha generato:

real    0m0.064s
user    0m0.040s
sys     0m0.020s
type

real    0m2.769s
user    0m1.620s
sys     0m1.130s

dichiarare è molto più veloce!

Si riduce all'uso di "dichiarare" per controllare l'output o il codice di uscita.

Stile di output:

isFunction() { [[ "$(declare -Ff "$1")" ]]; }

Utilizzo:

isFunction some_name && echo yes || echo no

Tuttavia, se la memoria serve, il reindirizzamento a null è più veloce della sostituzione dell'output (a proposito, il terribile e obsoleto metodo `cmd` dovrebbe essere bandito e utilizzato invece $(cmd).) E poiché dichiarato restituisce vero/falso se trovato/ non trovato e le funzioni restituiscono il codice di uscita dell'ultimo comando nella funzione, quindi di solito non è necessario un ritorno esplicito e poiché il controllo del codice di errore è più veloce del controllo di un valore di stringa (anche una stringa nulla):

Stile dello stato di uscita:

isFunction() { declare -Ff "$1" >/dev/null; }

Probabilmente è quanto di più conciso e benevolo si possa ottenere.

Velocità di test di diverse soluzioni

#!/bin/bash

f () {
echo 'This is a test function.'
echo 'This has more than one command.'
return 0
}

test_declare () {
    declare -f f > /dev/null
}

test_declare2 () {
    declare -F f > /dev/null
}

test_type () {
    type -t f | grep -q 'function'
}

test_type2 () {
    local var=$(type -t f)
    [[ "${var-}" = function ]]
}

post=
for j in 1 2; do
echo
echo 'declare -f' $post
time for i in $(seq 1 1000); do test_declare; done
echo
echo 'declare -F' $post
time for i in $(seq 1 1000); do test_declare2; done
echo
echo 'type with grep' $post
time for i in $(seq 1 1000); do test_type; done
echo
echo 'type with var' $post
time for i in $(seq 1 1000); do test_type2; done
unset -f f
post='(f unset)'
done

uscite ad esempio:

dichiarare -f

Real 0M0.037S Utente 0M0.024S SYS 0M0.012S

dichiarare -F

Real 0M0.030S Utente 0M0.020S SYS 0M0.008S

digitare con grep

Real 0M1.772S Utente 0M0.084S SYS 0M0.340S

digitare con var

reale 0m0.770s utente 0m0.096s sys 0m0.160s

dichiarare -f (f non impostato)

reale 0m0.031s utente 0m0.028s sys 0m0.000s

dichiarare -F (f non impostato)

Real 0M0.031S Utente 0M0.020S SYS 0M0.008S

digitare con grep (f non impostato)

Real 0M1.859S Utente 0M0.100S SYS 0M0.348S

digitare con var (f non impostato)

Real 0M0.683S Utente 0M0.092S SYS 0M0.160S

COSÌ declare -F f && echo function f exists. || echo function f does not exist. sembra essere la soluzione migliore.

fn_exists()
{
   [[ $(type -t $1) == function ]] && return 0
}

aggiornamento

isFunc () 
{ 
    [[ $(type -t $1) == function ]]
}

$ isFunc isFunc
$ echo $?
0
$ isFunc dfgjhgljhk
$ echo $?
1
$ isFunc psgrep && echo yay
yay
$

Questo ti dice se esiste, ma non che sia una funzione

fn_exists()
{
  type $1 >/dev/null 2>&1;
}

Mi è particolarmente piaciuta la soluzione di Gregorio Giuseppe

Ma l'ho modificato un po' per superare il "brutto trucco delle virgolette doppie":

function is_executable()
{
    typeset TYPE_RESULT="`type -t $1`"

    if [ "$TYPE_RESULT" == 'function' ]; then
        return 0
    else
        return 1
    fi
}

Dal mio commento su un'altra risposta (che continuo a perdere quando torno su questa pagina)

$ fn_exists() { test x$(type -t $1) = xfunction; }
$ fn_exists func1 && echo yes || echo no
no
$ func1() { echo hi from func1; }
$ func1
hi from func1
$ fn_exists func1 && echo yes || echo no
yes

Lo migliorerei in:

fn_exists()
{
    type $1 2>/dev/null | grep -q 'is a function'
}

E usalo in questo modo:

fn_exists test_function
if [ $? -eq 0 ]; then
    echo 'Function exists!'
else
    echo 'Function does not exist...'
fi

È possibile utilizzare 'type' senza alcun comando esterno, ma devi chiamarlo due volte, quindi risulta comunque circa due volte più lento della versione 'declare':

test_function () {
        ! type -f $1 >/dev/null 2>&1 && type -t $1 >/dev/null 2>&1
}

Inoltre questo non funziona in POSIX sh, quindi è totalmente inutile se non come curiosità!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top