Question Passer des paramètres à une fonction Bash


J'essaie de chercher comment passer des paramètres dans une fonction Bash, mais ce qui arrive 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?


672
2018-06-02 08:35


origine


Réponses:


Il existe deux façons 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 (pas par leur nom), c'est-à-dire 1 $, 2 $ et ainsi de suite. 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 c'est déclaré.

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

Référence: Advanced Bash-Scripting Guide.


1173
2018-06-02 08:57



La connaissance des langages de programmation de haut niveau (C / C ++ / Java / PHP / Python / Perl ...) suggérerait au profane que les fonctions de bash devraient fonctionner comme dans les autres langages. Au lieu, les fonctions bash fonctionnent comme des commandes shell et attendent que des arguments leur soient passés de la même manière que l'on pourrait passer une option à une commande shell (ls -l). En effet, arguments de fonction en bash sont traités comme paramètres de position ($1, $2..$9, ${10}, ${11}, etc). Ce n'est pas surprenant vu comment getopts travaux. Les parenthèses ne sont pas requises pour appeler une fonction dans bash.


(Remarque: Il se trouve que je travaille sur Open Solaris pour le 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

42
2018-05-10 20:30



Manquer les parenthèses et les virgules:

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

et la fonction devrait ressembler à ceci:

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

25
2018-06-02 08:36



Si vous préférez les paramètres nommés, il est possible (avec quelques astuces) de passer réellement les paramètres nommés aux 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 des arguments comme @required ou @readonly, créer ... des arguments de repos, créer des tableaux à partir d'arguments séquentiels (en utilisant par ex. string[4]) et éventuellement lister 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 compense un noyau plus lisible), mais vous pouvez en fait passer des tableaux (et des références à des variables - cette fonctionnalité ne fonctionne que dans bash 4.3)! De plus, les variables mappées sont toutes dans la portée locale, tout comme $ 1 (et autres).

Le code qui rend ce travail est assez léger et fonctionne à la fois dans bash 3 et bash 4 (ce sont les seules versions avec lesquelles j'ai testé). Si vous êtes intéressé par d'autres trucs comme celui-ci qui rendent le développement avec bash beaucoup plus agréable et plus facile, vous pouvez jeter un oeil à mon 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;'

23
2018-05-04 15:23



J'espère que cet exemple peut vous aider. Il prend deux nombres de l'utilisateur, les nourrit à la fonction appelée add (dans la toute dernière ligne du code), et add les résumera et les imprimera.

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

5
2017-10-24 06:49



Je pensais que je ferais pipi avec mention d'une autre façon de passer les paramètres nommés à bash ... passant par référence. Ceci est supporté depuis 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 syntaxe alternative pour bash 4.3 utilise un nameref

Bien que le nameref soit beaucoup plus pratique dans la mesure où il dereferences de manière transparente, certaines anciennes distributions prises en charge sont encore disponibles. Ancienne version donc je ne le recommanderai pas encore tout à fait.


3
2018-02-20 20:19



Un exemple simple qui effacera les deux lors de l'exécution du script ou dans un 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

1
2017-11-23 13:12