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. $0
is 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 getopts
werkt. 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 $1
misschien 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 add
Zal 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.