Come posso eseguire una funzione da uno script nella riga di comando?


119

Ho uno script che ha alcune funzioni.

Posso eseguire una delle funzioni direttamente dalla riga di comando?

Qualcosa come questo?

myScript.sh func()

Risposte:


66

Se lo script definisce solo le funzioni e non fa nient'altro, è possibile eseguire prima lo script nel contesto della shell corrente utilizzando il comando sourceo .e quindi chiamare semplicemente la funzione. Vedere help sourceper ulteriori informazioni.


1
L'unico problema con questo metodo è che se lo usi exitnella tua funzione, chiuderà il terminale dopo che la funzione è stata eseguita. C'è un modo per aggirare questo? @SvenMarnach
user1527227

@ user1527227: vai con la risposta successiva in questo caso, dato che hai il controllo dello script di shell. Se non lo fai, puoi chiamare prima una subshell interattiva (basta entrare bash) e exitterminerà solo la subshell, ma non il tuo terminale.
Sven Marnach

238

Bene, mentre le altre risposte sono corrette, puoi sicuramente fare qualcos'altro: se hai accesso allo script bash, puoi modificarlo e semplicemente posizionare alla fine il parametro speciale "$@"- che si espanderà agli argomenti della riga di comando si specifica, e poiché è "solo" la shell proverà a chiamarli parola per parola; e qui puoi specificare il nome della funzione come primo argomento. Esempio:

$ cat test.sh
testA() {
  echo "TEST A $1";
}

testB() {
  echo "TEST B $2";
}

"$@"


$ bash test.sh
$ bash test.sh testA
TEST A 
$ bash test.sh testA arg1 arg2
TEST A arg1
$ bash test.sh testB arg1 arg2
TEST B arg2

Per la lucidatura, puoi prima verificare che il comando esista ed è una funzione:

# Check if the function exists (bash specific)
if declare -f "$1" > /dev/null
then
  # call arguments verbatim
  "$@"
else
  # Show a helpful error
  echo "'$1' is not a known function name" >&2
  exit 1
fi

16
Utilizzare "$@"nella maggior parte dei casi. $@non è sicuro in alcuni casi.
fumiyas

1
Come eseguire più di una funzione? per esempio posso correre bash test.sh testA testB?
Jeff Pang

Anche questo deve essere avvolto con [ ! -z "$1" ]altrimenti la fonte solleverà la dichiarazione else in alcune versioni bash
JackLeo

Ho cercato da vicino e da lontano questa magica variabile "$ @" per utilizzare qualsiasi funzione sia chiamata su un file, grazie @sdaau!
Justin Hammond,

36

Il comando seguente registra prima la funzione nel contesto, quindi la chiama:

. ./myScript.sh && function_name

1
Puoi anche usare semplicemente source. Come in - source myScript.sh && function_name
stolen_leaves il

17

In breve, no.

Puoi importare tutte le funzioni nello script nel tuo ambiente con source( help sourceper i dettagli), che ti permetterà di chiamarle. Questo ha anche l'effetto di eseguire lo script, quindi fai attenzione.

Non c'è modo di chiamare una funzione da uno script di shell come se fosse una libreria condivisa.


1
Penso che questo dovrebbe essere dato più peso come risposta appropriata. Ho provato a fare qualcosa di simile a quello che vuole l'OP, ma lo scripting della shell semplicemente non è progettato per uno "sviluppo OOP pulito" (IMHO).
Dan L

4

utilizzando case

#!/bin/bash

fun1 () {
    echo "run function1"
    [[ "$@" ]] && echo "options: $@"
}

fun2 () {
    echo "run function2"
    [[ "$@" ]] && echo "options: $@"
}

case $1 in
    fun1) "$@"; exit;;
    fun2) "$@"; exit;;
esac

fun1
fun2

Questo script eseguirà le funzioni fun1 e fun2 ma se lo avvii con l'opzione fun1 o fun2 eseguirà solo una determinata funzione con args (se fornito) ed uscirà. uso

$ ./test 
run function1
run function2

$ ./test fun2 a b c
run function2
options: a b c

1

Modifica: ATTENZIONE - sembra che non funzioni in tutti i casi, ma funziona bene su molti script pubblici.

Se hai uno script bash chiamato "control" e al suo interno hai una funzione chiamata "build":

function build() { 
  ... 
}

Quindi puoi chiamarlo in questo modo (dalla directory in cui si trova):

./control build

Se è all'interno di un'altra cartella, ciò lo renderebbe:

another_folder/control build

Se il tuo file si chiama "control.sh", ciò renderebbe di conseguenza la funzione richiamabile in questo modo:

./control.sh build

1
Questo non ha funzionato nella shell interattiva per me. Ma ha funzionato:. ./control.sh && build
saulius2

1

Ho una situazione in cui ho bisogno di una funzione dallo script bash che non deve essere eseguita prima (ad esempio da source) e il problema @$è che myScript.sh viene quindi eseguito due volte, a quanto pare ... Quindi ho avuto l'idea per ottenere la funzione con sed:

sed -n "/^func ()/,/^}/p" myScript.sh

E per eseguirlo nel momento in cui ne ho bisogno, lo metto in un file e uso source:

sed -n "/^func ()/,/^}/p" myScript.sh > func.sh; source func.sh; rm func.sh


0

puoi chiamare la funzione dall'argomento della riga di comando come di seguito

function irfan() {
echo "Irfan khan"
date
hostname
}
function config() {
ifconfig
echo "hey"
}
$1

una volta terminata la funzione, metti $ 1 per accettare l'argomento, diciamo che il codice sopra viene salvato in fun.sh per eseguire la funzione ./fun.sh irfan e ./fun.sh config


0

Post risolto ma vorrei menzionare la mia soluzione preferita. Vale a dire, definire uno script generico di una riga eval_func.sh:

#!/bin/bash
source $1 && shift && "@a"

Quindi chiama qualsiasi funzione all'interno di qualsiasi script tramite:

./eval_func.sh <any script> <any function> <any args>...

Un problema che ho riscontrato con la soluzione accettata è che quando si procede al sourcing del mio script contenente la funzione all'interno di un altro script, gli argomenti di quest'ultimo sarebbero stati valutati dal primo, causando un errore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.