2010-10-19 6 views
26

A l'intérieur d'une fonction, $1 ... $n sont les paramètres transmis à cette fonction. En dehors d'une fonction $1 ... $n sont les paramètres transmis au script. Puis-je accéder d'une manière ou d'une autre aux paramètres passés au script dans une fonction?Accès aux arguments du script Bash dans une fonction

Répondre

20

Habituellement, il vous suffit de les transmettre en tant que paramètres à la fonction au moment de l'appel.

L'alternative (plus laide) est de les mettre dans des variables globales.

3

Vous devriez probablement utiliser "[email protected]" et le passer à la fin de la liste d'arguments de votre fonction. À l'intérieur de la fonction, shift après l'analyse de vos arguments et utilisez $1 à $n comme d'habitude.

6

Vous pouvez stocker tous vos arguments de script dans un tableau global:

args=("[email protected]") 

puis y accéder en fonction:

f(){ 
    echo ${args[0]} ${args[1]} 
} 
+1

Je pense que 'la fonction f() {' est pas valide. Vous devriez utiliser 'f() {' ou 'function f {' à la place. – Benoit

+0

J'ai corrigé ma réponse, mais 'function f() {}' a fonctionné pour moi. – dogbane

16

(je sais que c'est un ancien poste, mais aucun des réponses ont effectivement répondu à la question.)

Utilisez le tableau BASH_ARGV. Il contient les arguments passés au script appelant dans l'ordre inverse (c'est-à-dire, une pile avec le top à l'index 0). Vous devrez peut-être activer le débogage étendu dans le shebang (par exemple, #!/bin/bash -O extdebug) ou avec shopt (par exemple, shopt -s extdebug), mais cela fonctionne pour moi dans bash 4.2_p37 sans l'activer.

De man bash:

une variable tableau contenant tous les paramètres dans la pile d'appel d'exécution de bash en cours. Le dernier paramètre du dernier appel de sous-programme est en haut de la pile; le premier paramètre de l'appel initial est en bas. Quand un sous-programme est exécuté, les paramètres fournis sont poussés sur BASH_ARGV. Le shell ne définit BASH_ARGV qu'en mode de débogage étendu ....

Voici une fonction que j'utilise pour imprimer tous les arguments dans l'ordre sur une seule ligne:

# Print the arguments of the calling script, in order. 
function get_script_args 
{ 
    # Get the number of arguments passed to this script. 
    # (The BASH_ARGV array does not include $0.) 
    local n=${#BASH_ARGV[@]} 

    if (($n > 0)) 
    then 
     # Get the last index of the args in BASH_ARGV. 
     local n_index=$(($n - 1)) 

     # Loop through the indexes from largest to smallest. 
     for i in $(seq ${n_index} -1 0) 
     do 
      # Print a space if necessary. 
      if (($i < $n_index)) 
      then 
       echo -n ' ' 
      fi 

      # Print the actual argument. 
      echo -n "${BASH_ARGV[$i]}" 
     done 

     # Print a newline. 
     echo 
    fi 
} 
+0

bon à savoir. Bien que le débogage étendu semble un peu effrayant. – zedoo

10

Comme Benoit a déclaré, la solution la plus simple est de passer les arguments de ligne de commande pour la fonction comme arguments de la fonction avec [email protected] , alors vous pouvez les référencer exactement de la même manière qu'en dehors de la fonction. Vous allez référencer les valeurs passées à la fonction qui ont la même valeur que les arguments de la ligne de commande, gardez cela à l'esprit. Notez que cela vous empêche pratiquement de transmettre d'autres arguments à la fonction, à moins que vous ne sachiez exactement combien d'arguments seront passés sur la ligne de commande (ce qui est peu probable car cela dépend de l'utilisateur et n'est pas lié par votre contraintes)

ie

function fname { 
    # do something with $1 $2 $3...$n # 
    } 

    # [email protected] represents all the arguments passed at the command line # 
    fname [email protected] 

Une meilleure façon est de ne laisser passer que les arguments que vous savez que vous allez utiliser, de cette façon vous pouvez les utiliser dans la fonction et passer également d'autres paramètres à partir de votre code si vous souhaitez

-à-dire

function fname { 
    # do something with $1 $count $2 and $3 # 
    } 

    count=1 
    fname $1 $count $2 $3 
+2

Vous pouvez simplement passer un nombre fixe d'arguments à la fonction au début de la liste des arguments, puis après les avoir traités dans la fonction, utilisez shift pour les ignorer. ** Appel de fonction: ** 'fname farg1 farg2 farg3" $ @ "' ** Dans la fonction après le traitement des trois arguments: ** 'shift 3' – pabouk

+0

C'est un bon point. – CaffeineConnoisseur

+1

Vous pouvez également appeler fname en lui indiquant combien d'arguments utilisateur utilisent $ #, ce qui vous permet de spécifier non seulement des arguments supplémentaires avant, mais aussi après: 'fname beforearg $ #" $ @ "afterarg' –

0

Merci pour les conseils - ils m'ont inspiré pour écrire une fonction callstack. J'ai utilisé la commande 'column' pour l'esthétique.

callstack() { 
    local j=0 k prog=$(basename $0) 
    for ((i=1; ((i<${#BASH_ARGC[*]})); i++)) 
    do 
     echo -n "${FUNCNAME[$i]/main/$prog} " # function name 
     args="" 
     for ((k=0; ((k<${BASH_ARGC[$i]})); k++)) 
     do 
      args="${BASH_ARGV[$j]} $args" # arguments 
      let j++ 
     done 
     echo -e "$args\t|${BASH_LINENO[$i]}" $(sed -n ${BASH_LINENO[$i]}p "$0" 2>/dev/null) # line calling the function 
    done | column -t -s $'\t' -o ' ' | sed 1d # delete callstack entry 
} 
 
compareTemplates brother_001270_1.jpg  |163 compareTemplates "$f" # process the rest 
processPdf brother_001270.pdf    |233 filetype "${f%[*}" pdf && processPdf "$f" 
process brother_001270.pdf    |371 --process) shift; process "[email protected]"; exit ;; # process jpg or pdf 
sm --quiet --process brother_001270.pdf |0 
Questions connexes