Kann ich eine Funktion eines Shell-Skripts von einem anderen Shell-Skript aus aufrufen?

86

Ich habe 2 Shell-Skripte.

Das zweite Shell-Skript enthält die folgenden Funktionen second.sh

func1 
func2

Die Datei first.sh ruft das zweite Shell-Skript mit einigen Parametern auf und ruft func1 und func2 mit einigen anderen für diese Funktion spezifischen Parametern auf.

Hier ist das Beispiel dessen, wovon ich spreche

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

Wie kann ich das erreichen?

avirup
quelle
3
v=$(echo $1)ist völlig überflüssig. Schreib einfach fun2=$1. Der einzige Unterschied besteht darin, dass die $()(oder Backticks) nachfolgende Zeilenumbrüche entfernen.
William Pursell
1
Da das Aufrufen einer Funktion aus einem Shell-Skript im Gegensatz zur Befehlszeile nichts Besonderes ist, kann diese Frage auf "Wie rufe ich eine Bash-Funktion auf?" Reduziert werden.
Tom Russell

Antworten:

145

Überarbeiten Sie Ihr second.shSkript folgendermaßen:

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}"
}

Rufen Sie dann diese Funktionen first.shwie folgt aus dem Skript auf :

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

AUSGABE:

fun=love,book=horror
fun2=ball,book2=mystery
Anubhava
quelle
12
Um unbeabsichtigte Nebenwirkungen zu vermeiden, achten Sie darauf, dass der sourceBefehl das als Argument übergebene Skript tatsächlich ausführt.
dvlcube
43

Sie können eine Funktion in einem anderen Shell-Skript nicht direkt aufrufen.

Sie können Ihre Funktionsdefinitionen in eine separate Datei verschieben und sie dann mit dem folgenden .Befehl in Ihr Skript laden :

. /path/to/functions.sh

Dies wird so interpretiert, functions.shals ob der Inhalt zu diesem Zeitpunkt tatsächlich in Ihrer Datei vorhanden wäre. Dies ist ein gängiger Mechanismus zum Implementieren gemeinsam genutzter Bibliotheken von Shell-Funktionen.

Larsks
quelle
3
Ist das nicht dasselbe wie die akzeptierte Antwort, da .es sich um einen Alias ​​für handelt source?
Ajsharma
9
Nun, ich habe zuerst geantwortet, technisch gesehen ist die akzeptierte Antwort dieselbe wie diese :). Auch wenn dies in vielen Shells sourceein Alias .ist, ist dies nicht immer der Fall. Zum Beispiel hat das dashPaket unter Debian, das bereitstellt /bin/sh, keinen sourceBefehl.
Larsks
sourceBefehl funktionierte nicht in Ubuntu @ajsharma. Referenz:
Quellbefehl
so seltsam, dass dieser Kommentar nicht als der höchste bewertet wird? Dies ist die korrekte #! / Bin / sh-Syntax und die andere funktioniert nur in Bash.
xddq
20

Das Problem

Die aktuell akzeptierte Antwort funktioniert nur unter wichtigen Bedingungen. Gegeben...

/foo/bar/first.sh::

function func1 {  
   echo "Hello $1"
}

und

/foo/bar/second.sh::

#!/bin/bash

source ./first.sh
func1 World

Dies funktioniert nur, wenn das first.shaus demselben Verzeichnis ausgeführt wird, in dem first.shsich das befindet. Dh. Wenn der aktuelle Arbeitspfad der Shell lautet /foo, wird versucht, den Befehl auszuführen

cd /foo
./bar/second.sh

Druckfehler:

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

Dies source ./first.shliegt daran, dass der Pfad relativ zum aktuellen Arbeitspfad und nicht zum Pfad des Skripts ist. Daher könnte eine Lösung darin bestehen, Subshell zu verwenden und auszuführen

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

Generischere Lösung

Gegeben...

/foo/bar/first.sh::

function func1 {  
   echo "Hello $1"
}

und

/foo/bar/second.sh::

#!/bin/bash

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

func1 World

dann

cd /foo
./bar/second.sh

druckt

Hello World

Wie es funktioniert

  • $0 Gibt den relativen oder absoluten Pfad zum ausgeführten Skript zurück
  • dirname Gibt den relativen Pfad zum Verzeichnis zurück, in dem das $ 0-Skript vorhanden ist
  • $( dirname "$0" )Der dirname "$0"Befehl gibt den relativen Pfad zum Verzeichnis des ausgeführten Skripts zurück, das dann als Argument für den sourceBefehl verwendet wird
  • Hängt in "second.sh" /first.shnur den Namen des importierten Shell-Skripts an
  • source Lädt den Inhalt der angegebenen Datei in die aktuelle Shell
Patrik Stas
quelle
0

Wenn Sie definieren

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

in Datei1 (chmod 750 Datei1) und Datei2

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

und führen Sie ./file2 aus. Sie erhalten Fun1 aus Datei1. Hallo Fun1 aus Datei2. Hallo Überraschung !!! Sie überschreiben fun1 in Datei1 mit fun1 aus Datei2 ... Um dies nicht zu tun, müssen Sie dies tun

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

Es speichert Ihre vorherige Definition für fun1 und stellt sie mit dem vorherigen Namen wieder her, wobei nicht benötigte importierte gelöscht werden. Jedes Mal, wenn Sie Funktionen aus einer anderen Datei importieren, können Sie sich an zwei Aspekte erinnern:

  1. Sie können vorhandene mit denselben Namen überschreiben (wenn dies das gewünschte ist, müssen Sie sie wie oben beschrieben beibehalten).
  2. Importieren Sie den gesamten Inhalt der Importdatei (auch Funktionen und globale Variablen). Seien Sie vorsichtig! Es ist eine gefährliche Prozedur
Anatoly
quelle
-5
#vi function.sh

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

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

#sh function.sh

Hier f2ruft die Funktion die Funktion auff1

V. Santosh
quelle