J'essaie de chercher comment passer des paramètres dans une fonction Bash, mais ce qui revient, c'est toujours comment passer un paramètre à partir de la ligne de commande.
Je voudrais passer des paramètres dans mon script. J'ai essayé:
myBackupFunction("..", "...", "xx")
function myBackupFunction($directory, $options, $rootPassword) {
...
}
Mais la syntaxe n'est pas correcte, comment passer un paramètre à ma fonction?
Il y a deux manières typiques de déclarer une fonction. Je préfère la deuxième approche.
function function_name {
command...
}
ou
function_name () {
command...
}
Pour appeler une fonction avec des arguments:
function_name "$arg1" "$arg2"
La fonction fait référence aux arguments passés par leur position (et non par leur nom), c'est-à-dire $ 1, $ 2, etc. $ 0 est le nom du script lui-même.
Exemple:
function_name () {
echo "Parameter #1 is $1"
}
De plus, vous devez appeler votre fonction après la déclaration.
#!/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.
Sortie:
./myScript.sh: line 2: foo: command not found
Parameter #1 is 2
La connaissance de langages de programmation de haut niveau (C/C++/Java/PHP/Python/Perl ...) suggérerait au profane que les fonctions bash devraient fonctionner comme dans ces autres langages. À la place , les fonctions bash fonctionnent comme des commandes Shell et attendent que les arguments leur soient transmis de la même manière que l’on pourrait passer une option à une commande Shell (ls - l). En effet, les arguments de fonction de bash sont traités comme des paramètres de position ($1, $2..$9, ${10}, ${11}
, etc.). Ce n'est pas une surprise compte tenu du fonctionnement de getopts
. Les parenthèses ne sont pas obligées d'appeler une fonction dans bash.
(Note: Je travaille actuellement sur 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
Si vous préférez les paramètres nommés, il est possible (avec quelques astuces) de réellement transmettre des paramètres nommés à des fonctions (permet également de passer des tableaux et des références).
La méthode que j'ai développée vous permet de définir des paramètres nommés passés à une fonction comme celle-ci:
function example { args : string firstName , string lastName , integer age } {
echo "My name is ${firstName} ${lastName} and I am ${age} years old."
}
Vous pouvez également annoter les arguments en tant que @ requis ou @readonly, créer ... des arguments restants, créer des tableaux à partir d'arguments séquentiels (à l'aide, par exemple, de string[4]
) et éventuellement répertorier les arguments sur plusieurs lignes:
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[*]}"
}
En d'autres termes, non seulement vous pouvez appeler vos paramètres par leurs noms (ce qui constitue un noyau plus lisible), vous pouvez en fait passer des tableaux (et des références à des variables - cette fonctionnalité ne fonctionne toutefois que dans le bash 4.3)! De plus, les variables mappées sont toutes dans la portée locale, tout comme $ 1 (et autres).
Le code qui fait que cela fonctionne est assez léger et fonctionne à la fois dans bash 3 et bash 4 (ce sont les seules versions avec lesquelles je l’ai testé). Si vous êtes intéressé par d'autres astuces comme celle-ci qui rendent le développement avec bash beaucoup plus agréable et plus simple, vous pouvez jeter un oeil à my Bash Infinity Framework , le code ci-dessous est disponible comme l'une de ses fonctionnalités.
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;'
Oubliez les parens et les virgules:
myBackupFunction ".." "..." "xx"
et la fonction devrait ressembler à ceci:
function myBackupFunction() {
# here $1 is the first parameter, $2 the second etc.
}
J'espère que cet exemple peut vous aider. Il prend deux nombres de l'utilisateur, les alimente à la fonction appelée add
(à la toute dernière ligne du code), et add
les récapitule et les imprime.
#!/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
Je pensais que je pourrais ajouter une autre façon de passer des paramètres nommés à bash ... en passant par référence. Ceci est supporté à partir de 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];
Une autre syntaxe pour bash 4.3 utilise un nameref
Bien que le nameref soit beaucoup plus pratique en ce sens qu'il supprime de façon transparente les déréférences, certaines anciennes distributions supportées sont toujours accompagnées d'un ancienne version , je ne le recommanderai donc pas pour l'instant.
Un exemple simple qui effacera les deux lors de l'exécution du script ou à l'intérieur du script lors de l'appel d'une fonction.
#!/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