it-swarm.com.de

Parameter an eine Bash-Funktion übergeben

Ich versuche zu suchen, wie Parameter in einer Bash-Funktion übergeben werden, aber es wird immer angezeigt, wie Parameter über die Befehlszeile übergeben werden.

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 übergebe ich einen Parameter an meine Funktion?

859
stivlo

Es gibt zwei typische Arten, eine Funktion zu deklarieren. Ich bevorzuge den zweiten Ansatz.

function function_name {
   command...
} 

oder

function_name () {
   command...
} 

So rufen Sie eine Funktion mit Argumenten auf:

function_name "$arg1" "$arg2"

Die Funktion verweist auf übergebene Argumente anhand ihrer Position (nicht anhand des Namens), dh $ 1, $ 2 usw. $ 0 ist der Name des Skripts.

Beispiel:

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

Außerdem müssen Sie Ihre Funktion aufrufen, nachdem sie deklariert wurde .

#!/usr/bin/env sh

foo 1  # this will fail because foo has not been declared yet.

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

foo 2 # this will work.

Ausgabe:

./myScript.sh: line 2: foo: command not found
Parameter #1 is 2

Referenz: Advanced Bash-Scripting Guide .

1442
dogbane

Kenntnisse in höheren Programmiersprachen (C/C++/Java/PHP/Python/Perl ...) legen dem Laien nahe, dass Bash-Funktionen wie in diesen anderen Sprachen funktionieren sollten. Stattdessen funktionieren Bash-Funktionen wie Shell-Befehle und erwarten, dass Argumente auf die gleiche Weise an sie übergeben werden wie eine Option an einen Shell-Befehl (ls - l). Tatsächlich werden Funktionsargumente in bash als Positionsparameter ($1, $2..$9, ${10}, ${11} und so weiter). Dies ist keine Überraschung, wenn man bedenkt, wie getopts funktioniert. Klammern sind nicht erforderlich, um eine Funktion in der Bash aufzurufen.


(Hinweis: Ich arbeite gerade an Open Solaris.)

# bash style declaration for all you PHP/JavaScript junkies. :-)
# $1 is the directory to archive
# $2 is the name of the tar and zipped file when all is done.
function backupWebRoot ()
{
    tar -cvf - $1 | Zip -n .jpg:.gif:.png $2 - 2>> $errorlog &&
        echo -e "\nTarball created!\n"
}


# sh style declaration for the purist in you. ;-)
# $1 is the directory to archive
# $2 is the name of the tar and zipped file when all is done.
backupWebRoot ()
{
    tar -cvf - $1 | Zip -n .jpg:.gif:.png $2 - 2>> $errorlog &&
        echo -e "\nTarball created!\n"
}


#In the actual Shell script
#$0               $1            $2

backupWebRoot ~/public/www/ webSite.tar.Zip
56

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

Mit der von mir entwickelten Methode können Sie benannte Parameter definieren, die an eine Funktion wie die folgende übergeben werden:

function example { args : string firstName , string lastName , integer age } {
  echo "My name is ${firstName} ${lastName} and I am ${age} years old."
}

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

function example {
  args
    : @required string firstName
    : string lastName
    : integer age
    : string[] ...favoriteHobbies

  echo "My name is ${firstName} ${lastName} and I am ${age} years old."
  echo "My favorite hobbies include: ${favoriteHobbies[*]}"
}

Mit anderen Worten, Sie können Ihre Parameter nicht nur nach ihrem Namen aufrufen (was einen besser lesbaren Kern ausmacht), sondern Sie können auch Arrays (und Verweise auf Variablen - diese Funktion funktioniert jedoch nur in Bash 4.3) übergeben! Außerdem befinden sich die zugeordneten Variablen alle im lokalen Bereich, ebenso wie $ 1 (und andere).

Der Code, mit dem dies funktioniert, ist ziemlich leicht und funktioniert sowohl in Bash 3 als auch in Bash 4 (dies sind die einzigen Versionen, mit denen ich es getestet habe). Wenn Sie an weiteren Tricks wie diesen interessiert sind, die das Entwickeln mit Bash viel schöner und einfacher machen, können Sie sich mein Bash Infinity Framework ansehen. Der folgende Code ist als eine seiner Funktionen verfügbar.

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 # first colon ":" or next parameter's comma ","
    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 "Unexpected arguments after a rest array ($nextName) in '${FUNCNAME[1]}' function." >&2
        fi
      Elif [[ "$length" -gt 1 ]]
      then
        paramRange="{@:$paramIndex:$length}"
        paramIndex+=$((length - 1))
      fi

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

      # continue to the next param:
      shift
    fi
  done
  echo "${evalString} local -i __paramIndex=${paramIndex};"
}

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

Verpassen Sie die Parens und Kommas:

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

und die Funktion sollte so aussehen:

function myBackupFunction() {
   # here $1 is the first parameter, $2 the second etc.
}
26

Ich hoffe, dieses Beispiel kann Ihnen helfen. Der Benutzer nimmt zwei Zahlen entgegen, gibt sie an die Funktion add (in der letzten Codezeile) weiter und add fasst sie zusammen und druckt sie aus.

#!/bin/bash

read -p "Enter the first  value: " x
read -p "Enter the second value: " y

add(){
    arg1=$1 #arg1 gets to be the first  assigned argument (note there are no spaces)
    arg2=$2 #arg2 gets to be the second assigned argument (note there are no spaces)

    echo $(($arg1 + $arg2))
}

add x y #feeding the arguments
8
Milad P.

Ich dachte, ich würde eine andere Möglichkeit erwähnen, benannte Parameter an bash zu übergeben. Dies wird ab Bash 4.0 unterstützt

#!/bin/bash
function myBackupFunction(){ # directory options destination filename
local directory="$1" options="$2" destination="$3" filename="$4";
  echo "tar cz ${!options} ${!directory} | ssh [email protected] \"cat > /mnt/${!destination}/${!filename}.tgz\"";
}

declare -A backup=([directory]=".." [options]="..." [destination]="backups" [filename]="backup" );

myBackupFunction backup[directory] backup[options] backup[destination] backup[filename];

Eine alternative Syntax für Bash 4.3 verwendet ein nameref

Obwohl das nameref viel praktischer ist, da es nahtlos dereferenziert, liefern einige ältere unterstützte Distributionen immer noch ein ältere Version , so dass ich es noch nicht ganz empfehlen werde.

4
Wil

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

#!/bin/bash
echo "parameterized function example"
function print_param_value(){
    value1="${1}" # $1 represent first argument
    value2="${2}" # $2 represent second argument
    echo "param 1 is  ${value1}" #as string
    echo "param 2 is ${value2}"
    sum=$(($value1+$value2)) #process them as number
    echo "The sum of two value is ${sum}"
}
print_param_value "6" "4" #space sparted value
#you can also pass paramter durign executing script
print_param_value "$1" "$2" #parameter $1 and $2 during executing

#suppose our script name is param_example
# call like this 
# ./param_example 5 5
# now the param will be $1=5 and $2=5
4
Adiii