Posso chiamare una funzione di uno script di shell da un altro script di shell?


87

Ho 2 script di shell.

Il secondo script di shell contiene le seguenti funzioni second.sh

func1 
func2

Il first.sh chiamerà il secondo script di shell con alcuni parametri e chiamerà func1 e func2 con alcuni altri parametri specifici per quella funzione.

Ecco l'esempio di cosa sto parlando

second.sh

val1=`echo $1`
val2=`echo $2`

function func1 {

fun=`echo $1`
book=`echo $2`

}

function func2 {

fun2=`echo $1`
book2=`echo $2`


}

first.sh

second.sh cricket football

func1 love horror
func2 ball mystery

Come posso ottenerlo?



3
v=$(echo $1)è completamente ridondante. Basta scrivere fun2=$1. L'unica differenza è che $()(o i backtick) rimuoveranno le nuove righe finali.
William Pursell

1
Poiché non c'è niente di speciale nel chiamare una funzione da uno script di shell rispetto alla riga di comando, questa domanda può essere ridotta a "Come chiamare una funzione bash?"
Tom Russell

Risposte:


146

Rifattorizza il tuo second.shscript in questo modo:

function func1 {
   fun=$1
   book=$2
   printf "fun=%s,book=%s\n" "${fun}" "${book}"
}

function func2 {
   fun2=$1
   book2=$2
   printf "fun2=%s,book2=%s\n" "${fun2}" "${book2}"
}

E poi chiama queste funzioni dallo script in first.shquesto modo:

source ./second.sh
func1 love horror
func2 ball mystery

PRODUZIONE:

fun=love,book=horror
fun2=ball,book2=mystery

12
Per evitare effetti collaterali involontari, fai attenzione che il sourcecomando eseguirà effettivamente lo script passato come argomento.
dvlcube

44

Non è possibile chiamare direttamente una funzione in un altro script di shell.

È possibile spostare le definizioni delle funzioni in un file separato e quindi caricarle nello script utilizzando il .comando, in questo modo:

. /path/to/functions.sh

Questo interpreterà functions.shcome se il suo contenuto fosse effettivamente presente nel tuo file a questo punto. Questo è un meccanismo comune per l'implementazione di librerie condivise di funzioni di shell.


3
Non è la stessa della risposta accettata, poiché .è un alias per source?
ajsharma

10
Bene, ho risposto per primo, quindi tecnicamente la risposta accettata è la stessa di questa :). Inoltre, sebbene in molte shell sourcesia un alias ., non è sempre così. Ad esempio, il dashpacchetto su Debian, che fornisce /bin/sh, non ha un sourcecomando.
Larsks

sourceil comando non ha funzionato in Ubuntu @ajsharma. Riferimento: comando sorgente non trovato nella shell sh
rajeshmag

così strano che questo commento non sia votato come il più alto? Questa è la sintassi corretta #! / Bin / sh e l'altra funzionerà solo in bash.
xddq

21

Il problema

La risposta attualmente accettata funziona solo in condizioni importanti. Dato...

/foo/bar/first.sh:

function func1 {  
   echo "Hello $1"
}

e

/foo/bar/second.sh:

#!/bin/bash

source ./first.sh
func1 World

funziona solo se first.shviene eseguito dalla stessa directory in cui first.shsi trova. Cioè. se il percorso di lavoro corrente della shell è /foo, il tentativo di eseguire il comando

cd /foo
./bar/second.sh

stampa errore:

/foo/bar/second.sh: line 4: func1: command not found

Questo perché source ./first.shè relativo al percorso di lavoro corrente, non al percorso dello script. Quindi una soluzione potrebbe essere quella di utilizzare subshell ed eseguire

(cd /foo/bar; ./second.sh)

Soluzione più generica

Dato...

/foo/bar/first.sh:

function func1 {  
   echo "Hello $1"
}

e

/foo/bar/second.sh:

#!/bin/bash

source $(dirname "$0")/first.sh

func1 World

poi

cd /foo
./bar/second.sh

stampe

Hello World

Come funziona

  • $0 restituisce il percorso relativo o assoluto allo script eseguito
  • dirname restituisce il percorso relativo alla directory, dove esiste lo script $ 0
  • $( dirname "$0" )il dirname "$0"comando restituisce il percorso relativo alla directory dello script eseguito, che viene quindi utilizzato come argomento per il sourcecomando
  • in "second.sh", /first.shaggiunge semplicemente il nome dello script di shell importato
  • source carica il contenuto del file specificato nella shell corrente

0

Se definisci

    #!/bin/bash
        fun1(){
          echo "Fun1 from file1 $1"
        }
fun1 Hello
. file2 
fun1 Hello
exit 0

in file1 (chmod 750 file1) e file2

   fun1(){
      echo "Fun1 from file2 $1"
    }
    fun2(){
      echo "Fun1 from file1 $1"
    }

ed esegui ./file2 otterrai Fun1 da file1 Hello Fun1 da file2 Hello Surprise !!! Sovrascrivi fun1 in file1 con fun1 da file2 ... Per non farlo devi

declare -f pr_fun1=$fun1
. file2
unset -f fun1
fun1=$pr_fun1
unset -f pr_fun1
fun1 Hello

salva la tua definizione precedente per fun1 e ripristinala con il nome precedente eliminando quello importato non necessario. Ogni volta che importi funzioni da un altro file potresti ricordare due aspetti:

  1. puoi sovrascrivere quelli esistenti con lo stesso nome (se è quello che vuoi devi conservarli come descritto sopra)
  2. importa tutto il contenuto del file di importazione (funzioni e anche variabili globali) Fai attenzione! È una procedura pericolosa

-5
#vi function.sh

#!/bin/bash
f1() {
    echo "Hello $name"
}

f2() {
    echo "Enter your name: "
    read name
    f1
}
f2

#sh function.sh

Qui la funzione f2chiamerà funzionef1

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.