Wie kann ich eine Funktion über ein Skript in der Befehlszeile ausführen?


119

Ich habe ein Skript, das einige Funktionen hat.

Kann ich eine der Funktionen direkt über die Befehlszeile ausführen?

Etwas wie das?

myScript.sh func()

Antworten:


66

Wenn das Skript nur die Funktionen definiert und nichts anderes tut, können Sie das Skript zuerst im Kontext der aktuellen Shell mit dem Befehl sourceoder ausführen .und dann einfach die Funktion aufrufen. Siehe help sourcefür weitere Informationen.


1
Das einzige Problem bei dieser Methode ist, dass bei Verwendung exitin Ihrer Funktion das Terminal nach Ausführung der Funktion geschlossen wird. Gibt es einen Weg daran vorbei? @SvenMarnach
user1527227

@ user1527227: Fahren Sie in diesem Fall mit der nächsten Antwort fort, vorausgesetzt, Sie haben die Kontrolle über das Shell-Skript. Wenn Sie dies nicht tun, können Sie zuerst eine interaktive Unterschale aufrufen (einfach eingeben bash) und exitbeenden nur die Unterschale, nicht jedoch Ihr Terminal.
Sven Marnach

238

Nun, während die anderen Antworten richtig sind, können Sie sicherlich noch etwas anderes tun: Wenn Sie Zugriff auf das Bash-Skript haben, können Sie es ändern und einfach am Ende den speziellen Parameter "$@"einfügen, der auf die Argumente der Befehlszeile erweitert wird Sie geben an, und da es "allein" ist, versucht die Shell, sie wörtlich zu nennen. und hier können Sie den Funktionsnamen als erstes Argument angeben. Beispiel:

$ 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

Zum Polieren können Sie zunächst überprüfen, ob der Befehl vorhanden ist und eine Funktion ist:

# 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
Verwenden Sie "$@"in den meisten Fällen. $@ist in einigen Fällen nicht sicher.
Fumiyas

1
Wie kann man mehr als eine Funktion ausführen? Kann ich zum Beispiel laufen bash test.sh testA testB?
Jeff Pang

Dies muss auch mit einer [ ! -z "$1" ]anderen Quelle verpackt werden, die die else-Anweisung in einigen Bash-Versionen auslöst
JackLeo

Ich habe nah und fern nach dieser magischen "$ @" - Variablen gesucht, um die Funktion zu verwenden, die in einer Datei aufgerufen wird. Danke @sdaau!
Justin Hammond

36

Der folgende Befehl registriert die Funktion zuerst im Kontext und ruft sie dann auf:

. ./myScript.sh && function_name

1
Sie können auch einfach die Quelle verwenden. Wie in der Quelle myScript.sh && Funktionsname
gestohlene Blätter

17

Kurz gesagt, nein.

Sie können alle Funktionen des Skripts mit source( help sourcefür Details) in Ihre Umgebung importieren , um sie dann aufzurufen. Dies hat auch den Effekt, dass das Skript ausgeführt wird. Seien Sie also vorsichtig.

Es gibt keine Möglichkeit, eine Funktion aus einem Shell-Skript heraus aufzurufen, als wäre es eine gemeinsam genutzte Bibliothek.


1
Ich denke, dies sollte als angemessene Antwort mehr Gewicht erhalten. Ich habe versucht, etwas Ähnliches zu tun, wie es das OP will, aber Shell-Scripting ist einfach nicht für "Clean-Cut, OOP-Entwicklung" (IMHO) ausgelegt.
Dan L

4

Verwenden von 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

Dieses Skript führt die Funktionen fun1 und fun2 aus. Wenn Sie es jedoch mit der Option fun1 oder fun2 starten, wird die angegebene Funktion nur mit args (falls vorhanden) ausgeführt und beendet. Verwendung

$ ./test 
run function1
run function2

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

1

Bearbeiten: WARNUNG - scheint nicht in allen Fällen zu funktionieren, funktioniert aber bei vielen öffentlichen Skripten gut.

Wenn Sie ein Bash-Skript namens "control" haben und darin eine Funktion namens "build" haben:

function build() { 
  ... 
}

Dann können Sie es so aufrufen (aus dem Verzeichnis, in dem es sich befindet):

./control build

Wenn es sich in einem anderen Ordner befindet, würde dies Folgendes bewirken:

another_folder/control build

Wenn Ihre Datei "control.sh" heißt, würde dies die Funktion dementsprechend wie folgt aufrufen:

./control.sh build

1
Dies funktionierte in der interaktiven Shell für mich nicht. Aber das hat funktioniert:. ./control.sh && build
saulius2

1

Ich habe eine Situation, in der ich eine Funktion aus dem Bash-Skript benötige, die vorher nicht ausgeführt werden darf (z. B. von source), und das Problem dabei @$ist, dass myScript.sh dann anscheinend zweimal ausgeführt wird ... Also bin ich auf die Idee gekommen um die Funktion mit sed herauszuholen:

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

Und um es zu dem Zeitpunkt auszuführen, zu dem ich es brauche, lege ich es in eine Datei und verwende source:

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


0

Sie können die Funktion über das Befehlszeilenargument wie unten aufrufen

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

Sobald Sie die Funktion beendet haben, setzen Sie $ 1, um das Argument zu akzeptieren. Angenommen, der obige Code wird in fun.sh gespeichert, um die Funktion ./fun.sh irfan & ./fun.sh config auszuführen


0

Gelöster Beitrag, aber ich möchte meine bevorzugte Lösung erwähnen. Definieren Sie nämlich ein generisches Einzeilenskript eval_func.sh:

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

Rufen Sie dann eine beliebige Funktion in einem Skript auf über:

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

Ein Problem, auf das ich bei der akzeptierten Lösung gestoßen bin, ist, dass beim Beschaffen meines funktionshaltigen Skripts in einem anderen Skript die Argumente des letzteren vom ersteren ausgewertet werden und einen Fehler verursachen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.