Parameters doorgeven aan een Bash-functie

Ik probeer te zoeken hoe ik parameters kan doorgeven in een Bash-functie, maar wat altijd naar voren komt, is hoe ik een parameter kan doorgeven vanaf de opdrachtregel.

Ik wil graag parameters doorgeven in mijn script. Ik heb geprobeerd:

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

Maar de syntaxis is niet correct. Hoe kan ik een parameter doorgeven aan mijn functie?


Antwoord 1, autoriteit 100%

Er zijn twee typische manieren om een functie te declareren. Ik geef de voorkeur aan de tweede benadering.

function function_name {
   command...
} 

of

function_name () {
   command...
} 

Om een functie met argumenten aan te roepen:

function_name "$arg1" "$arg2"

De functie verwijst naar doorgegeven argumenten op basis van hun positie (niet op naam), dat wil zeggen $1, $2, enzovoort. $0is de naam van het script zelf.

Voorbeeld:

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

Je moet ook je functie aanroepen nadatdeze is gedeclareerd.

#!/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.

Uitvoer:

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

Referentie: Advanced Bash-Scripting Guide.


Antwoord 2, autoriteit 5%

Kennis van programmeertalen op hoog niveau (C/C++, Java, PHP, Python, Perl, enz.) zou de leek suggereren dat Bourne Again Shell (Bash)-functies zouden moeten werken zoals in die andere talen.

p>

In plaats daarvanwerken Bash-functies als shell-commando’s en verwachten ze dat er argumenten aan worden doorgegeven op dezelfde manier waarop men een optie aan een shell-commando zou kunnen doorgeven (bijv. ls -l). In feite worden functieargumentenin Bash behandeld als positionele parameters($1, $2..$9, ${10}, ${11}, enzovoort). Dit is geen verrassing als je bedenkt hoe getoptswerkt. Gebruik geen haakjes om een functie in Bash aan te roepen.


(Opmerking: ik werk toevallig aan OpenSolarisop het moment.)

# 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

Wilt u namen voor variabelen gebruiken? Doe gewoon iets dit.

local filename=$1 # The keyword declare can be used, but local is semantically more specific.

Wees echter voorzichtig. Als een argument voor een functie een spatie bevat, wilt u dit misschien in plaats daarvan doen! Anders is $1misschien niet wat je denkt dat het is.

local filename="$1" # Just to be on the safe side. Although, if $1 was an integer, then what? Is that even possible? Humm.

Wilt u een array doorgeven aan een functie?

callingSomeFunction "${someArray[@]}" # Expands to all array elements.

Behandel de argumenten in de functie als volgt.

function callingSomeFunction ()
{
    for value in "$@" # You want to use "$@" here, not "$*" !!!!!
    do
        :
    done
}

Moet je een waarde en een array doorgeven, maar toch “$@” gebruiken in de functie?

function linearSearch ()
{
    local myVar="$1"
    shift 1 # Removes $1 from the parameter list
    for value in "$@" # Represents the remaining parameters.
    do
        if [[ $value == $myVar ]]
        then
            echo -e "Found it!\t... after a while."
            return 0
        fi
    done
    return 1
}
linearSearch $someStringValue "${someArray[@]}"

Antwoord 3, autoriteit 4%

Als je de voorkeur geeft aan benoemde parameters, is het mogelijk (met een paar trucjes) om benoemde parameters daadwerkelijk door te geven aan functies (maakt het ook mogelijk om arrays en verwijzingen door te geven).

Met de methode die ik heb ontwikkeld, kun je benoemde parameters definiëren die worden doorgegeven aan een functie zoals deze:

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

Je kunt ook argumenten annoteren als @required of @readonly, …rest-argumenten maken, arrays maken van opeenvolgende argumenten (met bijvoorbeeld string[4]) en optioneel de argumenten in meerdere regels weergeven :

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[*]}"
}

Met andere woorden, je kunt niet alleen je parameters bij hun naam noemen (wat zorgt voor een beter leesbare kern), je kunt ook arrays (en verwijzingen naar variabelen – deze functie werkt echter alleen in Bash 4.3) doorgeven! Bovendien bevinden de toegewezen variabelen zich allemaal in het lokale bereik, net als $1(en andere).

De code waarmee dit werkt is vrij licht en werkt zowel in Bash 3 als in Bash 4 (dit zijn de enige versies waarmee ik het heb getest). Als je geïnteresseerd bent in meer van dit soort trucs die het ontwikkelen met bash veel leuker en gemakkelijker maken, kun je een kijkje nemen in mijn Bash Infinity Framework, de onderstaande code is beschikbaar als een van de functionaliteiten.

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 parameter:
      shift
    fi
  done
  echo "${evalString} local -i __paramIndex=${paramIndex};"
}
alias args='local __previousTrap=$(trap -p DEBUG); trap "eval \"\$(assignTrap \$BASH_COMMAND)\";" DEBUG;'

Antwoord 4, Autoriteit 2%

Drop de haakjes en komma’s:

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

en de functie moet er als volgt uitzien:

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

Antwoord 5

Het kost twee cijfers van de gebruiker, voedt ze naar de functie die add(in de allerlaatste regel van de code), en addZal ze samenvatten en print ze.

#!/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

Antwoord 6

Een eenvoudig voorbeeld dat zowel tijdens het uitvoeren van script- als inside script wissen tijdens het bellen van een functie.

#!/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-separated value
# You can also pass parameters during executing the script
print_param_value "$1" "$2" # Parameter $1 and $2 during execution
# Suppose our script name is "param_example".
# Call it like this:
#
# ./param_example 5 5
#
# Now the parameters will be $1=5 and $2=5

Antwoord 7

Een andere manier om benoemde parameters door te geven aan Bash… is het doorgeven via referentie. Dit wordt ondersteund vanaf Bash 4.0

#!/bin/bash
function myBackupFunction(){ # directory options destination filename
local directory="$1" options="$2" destination="$3" filename="$4";
  echo "tar cz ${!options} ${!directory} | ssh root@backupserver \"cat > /mnt/${!destination}/${!filename}.tgz\"";
}
declare -A backup=([directory]=".." [options]="..." [destination]="backups" [filename]="backup" );
myBackupFunction backup[directory] backup[options] backup[destination] backup[filename];

Een alternatieve syntaxis voor Bash 4.3 is het gebruik van een nameref.

Hoewel de naamref een stuk handiger is omdat het naadloos dereferenties verwijdert, leveren sommige oudere ondersteunde distributies nog steeds een oudere versie, dus ik zal het nog niet helemaal aanbevelen.

Other episodes