funzione di chiamata dichiarata di seguito


15

È possibile chiamare una funzione dichiarata di seguito in bash?

Esempio

if [ "$input" = "yes" ]; then
    YES_FUNCTION
elif [ "$input" = "no" ]; then
    NO_FUNCTION
else
    exit 0;
fi

YES_FUNCTION()
{
  .....
  .....
}

NO_FUNCTION()
{
  .....
  .....
}

Risposte:


36

Come altri hanno già detto, non puoi farlo.

Ma se vuoi disporre il codice in un file in modo che il programma principale si trovi nella parte superiore del file e le altre funzioni siano definite di seguito, puoi farlo avendo una mainfunzione separata .

Per esempio

#!/bin/sh

main() {
    if [ "$1" = yes ]; then
        do_task_this
    else
        do_task_that
    fi
}

do_task_this() {
    ...
} 
do_task_that() {
    ...
} 

main "$@"; exit

Quando chiamiamo mainalla fine del file, tutte le funzioni sono già definite. È necessario passare esplicitamente "$@"a mainper rendere visibili gli argomenti della riga di comando dello script nella funzione.

L'esplicito exitsulla stessa riga della chiamata a main non è obbligatorio, ma può essere utilizzato per evitare che uno script in esecuzione venga incasinato se il file di script viene modificato. Senza di essa, la shell proverebbe a continuare a leggere i comandi dal file di script dopo i mainritorni. (vedi Come leggere l'intero script della shell prima di eseguirlo? )


@ikkachu penso che dovrebbe funzionare .. fammi controllare.
msp9011,

7
Con gli script Bash uso spesso [[ ${BASH_SOURCE[0]} = "$0" ]] && Main "$@"per chiamare la funzione principale in modo da poterlo rintracciare in un altro script senza Mainessere eseguito. Quindi posso riutilizzare le funzioni o scrivere test per controllarle.
BlackJack,

11
Avere main "$@"; exit(con exitsulla stessa riga di main) è anche utile come protezione contro il file che viene modificato mentre viene interpretato.
Stéphane Chazelas,

2
@JoL, ciò che viene letto non viene letto di nuovo, e la shell dovrà leggere e analizzare l'intero testo di un ciclo prima di iniziare a eseguirlo, ma poi dopo che il ciclo ritorna continuerà a leggere dal resto del file in la posizione corrente (e se il file è stato modificato, rovinerà tutto). Se tutto è nelle funzioni, la shell deve leggere tutto prima di iniziare a fare qualsiasi cosa (tranne che per definire quelle funzioni), se mettiamo exitla stessa linea in quanto mainci assicuriamo che la shell non rileggerà nulla dal file dopo la mainrestituzione.
Stéphane Chazelas,

1
@MontyHarder, non importa se si utilizza main; exit, main; exit $?o main <EOF>, in ogni caso, il codice di uscita mainviene utilizzato come codice di uscita dello script. Il exitsarebbe solo per evitare che le cose sempre incasinato se qualcuno modifica lo script mentre è in esecuzione.
ilkkachu,

13

No, le funzioni devono esistere nell'ambiente shell al momento della loro chiamata.

La "Guida allo stile di shell" di Google ha una correzione per questo:

Una funzione chiamata mainè necessaria per gli script abbastanza a lungo da contenere almeno un'altra funzione.

Alla fine dello script, dopo tutte le funzioni, come unica affermazione non in una funzione, avresti

main "$@"

Ciò chiamerebbe la mainfunzione con qualunque parametro sia stato dato lo script. La mainfunzione potrebbe trovarsi nella parte superiore dello script (la guida di stile dice di metterla in fondo, ma poi dice molte cose).

Quando la shell arriva alla mainchiamata, tutte le funzioni nello script sono state analizzate e possono quindi essere richiamate dall'interno della mainfunzione.


9

No, le funzioni devono essere dichiarate prima di essere utilizzate. Gli script della shell vengono letti riga per riga e agiscono riga per riga; quindi una funzione non esiste fino a quando non viene eseguita la sua dichiarazione.


hai ragione. il problema è che ho più di 30 funzioni in uno script. è abbastanza complicato quando leggiamo il codice. In Cè comodo.
msp9011,

3
È possibile inserire le dichiarazioni delle funzioni in un altro file e sorgente ( . yourfile).
Stephen Kitt,

Sì, l'ho provato, ma il requisito è avere un singolo script.
msp9011,

@SivaPrasath Qual è esattamente il problema? Basta definire tutte le funzioni, magari anche inserendo il codice principale in una funzione e quindi l'ultima riga mostra quale funzione viene chiamata e contiene la parte principale dello script.
BlackJack,

@SivaPrasath In C, non hai ifdichiarazioni nude al di fuori di una funzione. Non è necessario definire la funzione quando si dichiara la iffunzione contenente, proprio quando la si chiama .
Chepner,

4

La shell non ha il concetto di declaringuna funzione. Quindi non puoi avere una dichiarazione in avanti.

Di conseguenza, è necessario che l'implementazione della funzione sia letta dalla shell prima che possa essere chiamata.


4
Tecnicamente, alcune shell (ksh, zsh) hanno una funzione di caricamento automatico che potrebbe essere vista come una qualche forma di dichiarazione (dove autoload fdichiara la funzione, ma il suo corpo viene caricato solo alla prima invocazione). Ciò non si applica tuttavia ai PO bash.
Stéphane Chazelas,
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.