Funktion mit Namen mit Argumenten aufrufen

Oct 20 2020

Ich bin ziemlich neu in der Shell-Scripting-Front und habe mich gefragt, ob es möglich ist, eine Funktion aufzurufen, die selbst eine andere Funktion mit keinem, einem oder mehreren Argumenten aufruft. Das erste Argument wäre der Name der aufzurufenden Funktion, jedes andere Argument ist ein Argument für die aufzurufende Funktion.

Als Hintergrund möchte ich ein Shell-Skript schreiben, um einige integrierte OpenFOAM-Funktionen zu verwenden, nämlich runParallelund runApplication, die ich zur Verdeutlichung runSerialim obigen Beispiel aufgerufen habe . Diese Funktionen führen verschiedene Aktionen aus, da der Name andeutet, dass sie einen Befehl entweder im seriellen oder im parallelen Modus ausführen.

Eine Simulation in OpenFOAM besteht aus mehreren Funktionsaufrufen und alles, was ich tun möchte, ist, den Code so zu kürzen, dass stattdessen

#!/bin/sh

# $n_core is a user input how many cores to use printf 'On how many cores do you want to run the simulation?' read -r n_core if [ $n_core -eq "1" ]; then
  runSerial "functionOne"  # no arguments here
  runSerial "functionTwo" "arg1"
  runSerial "functionThree" "arg1" "arg2"
  ...
else
  runParallel "functionOne"  # no arguments here
  runParallel "functionTwo" "arg1"
  runParallel "functionThree" "arg1" "arg2"
  ...
fi

Ich fragte mich, ob ich das durch so etwas ersetzen könnte

#!/bin/sh

runSerialOrParallel()
{
    if [ $n_core -eq "1" ]; then runSerial "$1" "$2" ... else runParallel "$1" "$2" ... fi } # $n_core is a user input how many cores to use
printf 'On how many cores do you want to run the simulation?'
read -r n_core

runSerialOrParallel "functionOne"  # no arguments here
runSerialOrParallel "functionTwo" "arg1"
runSerialOrParallel "functionThree" "arg1" "arg2"

Im Moment stecke ich bei der Frage fest, wie die Argumente für die Funktion zu erklären sind, die meine runSerialOrParallelFunktion selbst aufrufen soll. Wenn ich functionTwoalso seriell oder parallel ausgeführt werden möchte , mit einem Argument für sich functionTwoselbst, wie kann ich das im Inneren erreichen runSerialOrParallel?

Jede Hilfe wäre sehr dankbar und bitte verzeihen Sie mir, wenn es eine profane Antwort auf diese Frage gibt, die ich leicht hätte finden können, aber nicht.

Prost!

(Ich hoffe, die Bearbeitung hat einige Dinge geklärt, mein schlechtes ..)

Antworten

1 StéphaneChazelas Oct 20 2020 at 14:53

In Bourne-ähnlichen Shells "$@"(beachten Sie, dass die Anführungszeichen wichtig sind!) Wird auf alle Argumente des Skripts oder der Funktion erweitert, wenn diese innerhalb einer Funktion erweitert werden.

runSerialOrParallel()
{
    if [ "$n_core" -eq 1 ]; then
        runSerial "$@" else runParallel "$@"
    fi
}

Würde runSerialOrParallelaufrufen runSerialoder runParallelmit den gleichen Argumenten, die es selbst erhalten hat. Wenn das erste Argument ein Funktionsname sein soll und die folgenden weiteren Argumente an diese Funktion übergeben werden sollen, runSerialkönnte Ihre Funktion ungefähr so ​​aussehen:

runSerial() {
  printf 'Running "%s" with %u argument%s:\n' "$1" "$(($# - 1))" "${3+s}"
  "$@"
}

(Beachten Sie, dass es hier keinen Unterschied macht, ob das erste Argument eine Funktion, ein externer Befehl oder ein eingebautes Argument ist.)

Oder:

runSerial() {
  funcName=${1?No function specified}
  shift # removes the func name from the arguments

  printf 'Running "%s" with %u argument%s:\n' "$funcName" "$#" "${2+s}" "$funcName" "$@"
}

(Das wird ${2+s}erweitert, swenn das zweite Argument (anfangs das dritte) angegeben wird, um "Argument" in mehrere "Argumente" umzuwandeln, wenn mindestens zwei Argumente $funcNameangegeben werden sollen.)

$ runSerial echo foo bar
Running "echo" with 2 arguments:
foo bar
$ runSerial echo foo Running "echo" with 1 argument: foo $ n_core=1
$ runSerialOrParallel echo foo
Running "echo" with 1 argument:
foo