1321 Stimmen

Übergeben von Parametern an eine Bash-Funktion

Ich versuche herauszufinden, wie man Parameter in einer Bash-Funktion übergibt, aber was immer angezeigt wird, ist, wie man Parameter von der Befehlszeile übergibt.

Ich möchte Parameter innerhalb meines Skripts übergeben. Ich habe es versucht:

myBackupFunction("..", "...", "xx")

function myBackupFunction($directory, $options, $rootPassword) {
     ...
}

Aber die Syntax ist nicht korrekt. Wie kann ich einen Parameter an meine Funktion übergeben?

2065voto

dogbane Punkte 253146

Es gibt zwei typische Möglichkeiten, eine Funktion zu deklarieren. Ich bevorzuge den zweiten Ansatz.

function function_name {
   Befehl...
} 

oder

function_name () {
   Befehl...
} 

Um eine Funktion mit Argumenten aufzurufen:

function_name "$arg1" "$arg2"

Die Funktion bezieht sich auf übergebene Argumente nach ihrer Position (nicht nach Namen), das heißt $1, $2 und so weiter. $0 ist der Name des Skripts selbst.

Beispiel:

function_name () {
   echo "Parameter #1 ist $1"
}

Sie müssen Ihre Funktion auch nach ihrer Deklaration aufrufen.

#!/usr/bin/env sh

foo 1  # dies wird fehlschlagen, weil foo noch nicht deklariert wurde.

foo() {
    echo "Parameter #1 ist $1"
}

foo 2 # dies wird funktionieren.

Ausgabe:

./myScript.sh: Zeile 2: foo: Befehl nicht gefunden
Parameter #1 ist 2

Referenz: Fortgeschrittener Bash-Scripting-Leitfaden.

145voto

Anthony Rutledge Punkte 5794

Das Wissen über Hochsprachen (C/C++, Java, PHP, Python, Perl, usw.) würde dem Laien nahelegen, dass Bourne Again Shell (Bash)-Funktionen genauso funktionieren sollten wie in diesen anderen Sprachen.

Stattdessen arbeiten Bash-Funktionen wie Shell-Befehle und erwarten, dass Argumente genauso übergeben werden wie man einer Option bei einem Shell-Befehl übergibt (z. B. ls -l). In der Tat werden Funktionsargumente in Bash als Positionsparameter behandelt ($1, $2..$9, ${10}, ${11} und so weiter). Dies ist keine Überraschung, wenn man bedenkt, wie getopts funktioniert. Verwenden Sie keine Klammern zur Ausführung einer Funktion in Bash.


(Hinweis: Ich arbeite gerade zufällig an OpenSolaris.)

# Bash-Style-Deklaration für alle PHP/JavaScript-Junkies. :-)
# $1 ist das zu archivierende Verzeichnis
# $2 ist der Name der tar- und zip-Datei, wenn alles erledigt ist.
function backupWebRoot ()
{
    tar -cvf - "$1" | zip -n .jpg:.gif:.png "$2" - 2>> $errorlog &&
        echo -e "\nTarball erstellt!\n"
}

# sh-Style-Deklaration für den Puristen in dir. ;-)
# $1 ist das zu archivierende Verzeichnis
# $2 ist der Name der tar- und zip-Datei, wenn alles erledigt ist.
backupWebRoot ()
{
    tar -cvf - "$1" | zip -n .jpg:.gif:.png "$2" - 2>> $errorlog &&
        echo -e "\nTarball erstellt!\n"
}

# Im eigentlichen Shell-Skript
# $0               $1            $2

backupWebRoot ~/public/www/ webSite.tar.zip

Möchten Sie Namen für Variablen verwenden? Mach einfach das hier.

lokale Dateiname=$1 # Das Schlüsselwort declare kann verwendet werden, aber local ist semantisch genauer.

Sei jedoch vorsichtig. Wenn ein Argument einer Funktion ein Leerzeichen enthält, möchten Sie vielleicht stattdessen dies tun! Andernfalls ist $1 vielleicht nicht das, was du denkst.

lokale Dateiname="$1" # Nur um auf der sicheren Seite zu sein. Obwohl, wenn $1 eine ganze Zahl war, was dann? Ist das überhaupt möglich? Humm.

Möchten Sie ein Array an eine Funktion nach Wert übergeben?

callingSomeFunction "${someArray[@]}" # Erweitert sich auf alle Array-Elemente.

In der Funktion behandeln Sie die Argumente so.

function callingSomeFunction ()
{
    für Wert in "$@" # Sie sollten hier "$@" verwenden, nicht "$*" !!!!!
    tu
        :
    fertig
}

Müssen Sie einen Wert und ein Array übergeben, aber trotzdem "$@" in der Funktion verwenden?

function linearSearch ()
{
    lokale myVar="$1"

    shift 1 # Entfernt $1 aus der Parameterliste

    für Wert in "$@" # Stellt die verbleibenden Parameter dar.
    tu
        wenn [[ $Wert == $myVar ]]
        dann
            echo -e "Gefunden!\t... nach einer Weile."
            rückkehr 0
        fi
    fertig

    zurückkehren 1
}

linearSearch $someStringValue "${someArray[@]}"

In Bash 4.3 und höher können Sie ein Array an eine Funktion durch Verweis übergeben, indem Sie den Parameter einer Funktion mit der -n-Option definieren.

function callingSomeFunction ()
{
    lokale -n someArray=$1 # auch ${1:?} um den Parameter obligatorisch zu machen.

    für Wert in "${someArray[@]}" # Schön!
    tu
        :
    fertig
}

callingSomeFunction myArray # Kein $ vor dem Argument. Sie übergeben per Namen, nicht durch Expansion / Wert.

82voto

niieani Punkte 3693

Wenn Sie benannte Parameter bevorzugen, ist es möglich (mit ein paar Tricks), tatsächlich benannte Parameter an Funktionen zu übergeben (es ermöglicht auch das Übergeben von Arrays und Referenzen).

Die Methode, die ich entwickelt habe, ermöglicht es Ihnen, benannte Parameter, die an eine Funktion übergeben werden, wie folgt zu definieren:

Funktion Beispiel { args: Zeichenkette Vorname, Zeichenkette Nachname, Ganze Zahl Alter } {
  echo "Mein Name ist ${Vorname} ${Nachname} und ich bin ${Alter} Jahre alt."
}

Sie können auch Argumente als @required oder @readonly annotieren, ...rest-Argumente erstellen, Arrays aus sequentiellen Argumenten erstellen (z.B. Zeichenkette[4]) und optional die Argumente in mehreren Zeilen auflisten:

Funktion Beispiel {
  args
    : @required Zeichenkette Vorname
    : Zeichenkette Nachname
    : Ganze Zahl Alter
    : Zeichenkette[] ...Lieblingshobbys

  echo "Mein Name ist ${Vorname} ${Nachname} und ich bin ${Alter} Jahre alt."
  echo "Meine Lieblingshobbys sind: ${Lieblingshobbys[*]}"
}

Mit anderen Worten, nicht nur können Sie Ihre Parameter mit ihren Namen aufrufen (was für ein lesbareres Kernstück sorgt), Sie können tatsächlich Arrays (und Verweise auf Variablen - diese Funktion funktioniert jedoch nur in Bash 4.3)! Außerdem sind die zugeordneten Variablen alle im lokalen Gültigkeitsbereich, genauso wie $1 (und andere).

Der Code, der dies ermöglicht, ist ziemlich leicht und funktioniert sowohl in Bash 3 als auch in Bash 4 (das sind die einzigen Versionen, mit denen ich es getestet habe). Wenn Sie an weiteren Tricks wie diesem interessiert sind, die die Entwicklung mit bash wesentlich angenehmer und einfacher machen, können Sie sich mein Bash Infinity Framework anschauen, der folgende Code ist eine seiner Funktionalitäten.

shopt -s expand_aliases

function assignTrap {
  local evalString
  local -i paramIndex=${__paramIndex-0}
  local initialCommand="${1-}"

  if [[ "$initialCommand" != ":" ]]
  then
    echo "trap - DEBUG; eval \"${__previousTrap}\"; unset __previousTrap; unset __paramIndex;"
    return
  fi

  while [[ "${1-}" == "," || "${1-}" == "${initialCommand}" ]] || [[ "${#@}" -gt 0 && "$paramIndex" -eq 0 ]]
  do
    shift # Erstes Doppelpunkt ":" oder nächstes Komma des Parameters ","
    paramIndex+=1
    local -a decorators=()
    while [[ "${1-}" == "@"* ]]
    do
      decorators+=( "$1" )
      shift
    done

    local declaration=
    local wrapLeft='"'
    local wrapRight='"'
    local nextType="$1"
    local length=1

    case ${nextType} in
      string | boolean) declaration="local " ;;
      integer) declaration="local -i" ;;
      reference) declaration="local -n" ;;
      arrayDeclaration) declaration="local -a"; wrapLeft= ; wrapRight= ;;
      assocDeclaration) declaration="local -A"; wrapLeft= ; wrapRight= ;;
      "string["*"]") declaration="local -a"; length="${nextType//[a-z\[\]]}" ;;
      "integer["*"]") declaration="local -ai"; length="${nextType//[a-z\[\]]}" ;;
    esac

    if [[ "${declaration}" != "" ]]
    then
      shift
      local nextName="$1"

      for decorator in "${decorators[@]}"
      do
        case ${decorator} in
          @readonly) declaration+="r" ;;
          @required) evalString+="[[ ! -z \$${paramIndex} ]] || echo \"Parameter '$nextName' ($nextType) is marked as required by '${FUNCNAME[1]}' function.\"; " >&2 ;;
          @global) declaration+="g" ;;
        esac
      done

      local paramRange="$paramIndex"

      if [[ -z "$length" ]]
      then
        # ...rest
        paramRange="{@:$paramIndex}"
        # trim leading ...
        nextName="${nextName//\./}"
        if [[ "${#@}" -gt 1 ]]
        then
          echo "Unerwartete Argumente nach einem Rest-Array ($nextName) in der Funktion '${FUNCNAME[1]}'." >&2
        fi
      elif [[ "$length" -gt 1 ]]
      then
        paramRange="{@:$paramIndex:$length}"
        paramIndex+=$((length - 1))
      fi

      evalString+="${declaration} ${nextName}=${wrapLeft}\$${paramRange}${wrapRight}; "

      # Weiter zum nächsten Parameter:
      shift
    fi
  done
  echo "${evalString} local -i __paramIndex=${paramIndex};"
}

alias args='local __previousTrap=$(trap -p DEBUG); trap "eval \"\$(assignTrap \$BASH_COMMAND)\";" DEBUG;'

45voto

Entfernen Sie die Klammern und Kommas:

 myBackupFunction ".." "..." "xx"

Und die Funktion sollte so aussehen:

function myBackupFunction() {
    # Hier ist $1 der erste Parameter, $2 der zweite usw.
}

17voto

Adiii Punkte 43331

Ein einfaches Beispiel, das sowohl während der Ausführung des Skripts als auch innerhalb des Skripts beim Aufruf einer Funktion gelöscht wird.

#!/bin/bash
echo "Beispiel für eine parametrisierte Funktion"
function print_param_value(){
    value1="${1}" # $1 stellt das erste Argument dar
    value2="${2}" # $2 stellt das zweite Argument dar
    echo "Parameter 1 ist ${value1}" # Als String
    echo "Parameter 2 ist ${value2}"
    sum=$(($value1+$value2)) # Verarbeite sie als Zahlen
    echo "Die Summe der beiden Werte beträgt ${sum}"
}
print_param_value "6" "4" # Leerzeichen-getrennte Werte
# Sie können auch Parameter während der Ausführung des Skripts übergeben
print_param_value "$1" "$2" # Parameter $1 und $2 während der Ausführung

# Angenommen, der Name unseres Skripts ist "param_example".
# Rufen Sie es so auf:
#
# ./param_example 5 5
#
# Nun werden die Parameter $1=5 und $2=5 sein

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X