Come accedere agli argomenti della riga di comando del chiamante all'interno di una funzione?


95

Sto tentando di scrivere una funzione in bash che accederà agli argomenti della riga di comando degli script, ma vengono sostituiti con gli argomenti posizionali della funzione. C'è un modo per la funzione di accedere agli argomenti della riga di comando se non vengono passati esplicitamente?

# Demo function
function stuff {
  echo $0 $*
}

# Echo's the name of the script, but no command line arguments
stuff

# Echo's everything I want, but trying to avoid
stuff $*

3
Sono un po 'confuso, vuoi le discussioni senza passarle?
Ravi Vyas

4
Sì, il punto è ottenere anche gli argomenti della riga di comando dall'interno di una funzione senza passarli come argomenti funzionali. Ha a che fare con una situazione di gestione degli errori in cui desidero eseguire la gestione degli errori in base agli argomenti della riga di comando indipendentemente dagli argomenti passati alla funzione.
DonGar

Cordiali saluti, $*è estremamente buggy - è cambierà ./yourScript "first argument" "second argument"a ./yourscript "first" "argument" "second" "argument", o modificare ./yourscript '*.txt'a qualcosa di simile ./yourscript one.txt two.txt, nonostante le virgolette.
Charles Duffy

Risposte:


46

La mia lettura del manuale di bash ref dice che questa roba è catturata in BASH_ARGV, sebbene parli molto di "stack".

#!/bin/bash

function argv {
    for a in ${BASH_ARGV[*]} ; do
      echo -n "$a "
    done
    echo
}

function f {
    echo f $1 $2 $3
    echo -n f ; argv
}

function g {
    echo g $1 $2 $3
    echo -n g; argv
    f
}

f boo bar baz
g goo gar gaz

Salva in f.sh

$ ./f.sh arg0 arg1 arg2
f boo bar baz
farg2 arg1 arg0 
g goo gar gaz
garg2 arg1 arg0 
f
farg2 arg1 arg0 

5
Si noti che l'iterazione dell'array in questo modo fa sì che gli argomenti siano in ordine inverso dalla riga di comando.
Andrew Backer

93

Se vuoi avere i tuoi argomenti in stile C (array di argomenti + numero di argomenti) puoi usare $@e $#.

$#ti dà il numero di argomenti.
$@ti dà tutti gli argomenti. Puoi trasformarlo in un array con args=("$@").

Quindi per esempio:

args=("$@")
echo $# arguments passed
echo ${args[0]} ${args[1]} ${args[2]}

Nota che qui in ${args[0]}realtà è il primo argomento e non il nome del tuo script.


5
Questo non risolve la domanda: si tratta di passare gli argomenti della riga di comando a una funzione di shell.
Cascabel

6
@Jefromi, in realtà, risponde perfettamente alla domanda. È possibile utilizzare l' argsarray dall'interno di una funzione, se lo si inizializza in anticipo come descritto.
vadipp

1
Lo trovo molto più pulito rispetto all'iterazione sugli argomenti.
Félix Gagnon-Grenier

1
Questo è semplice e facile. Bella risposta. L'hai pubblicato più di 7 anni fa, quindi ciao dal futuro: luglio 2017
SDsolar

Ancora meglio sarebbe citare come echo "${args[0]} ${args[1]} ${args[2]}", o gli argomenti sono soggetti all'espansione del nome del file.
Benjamin W.

17
#!/usr/bin/env bash

echo name of script is $0
echo first argument is $1
echo second argument is $2
echo seventeenth argument is $17
echo number of arguments is $#

Modifica: vedere il mio commento sulla domanda


16

Il commento di Ravi è essenzialmente la risposta. Le funzioni prendono i propri argomenti. Se vuoi che siano gli stessi degli argomenti della riga di comando, devi passarli. Altrimenti, stai chiaramente chiamando una funzione senza argomenti.

Detto questo, potresti, se ti piace, memorizzare gli argomenti della riga di comando in un array globale da utilizzare all'interno di altre funzioni:

my_function() {
    echo "stored arguments:"
    for arg in "${commandline_args[@]}"; do
        echo "    $arg"
    done
}

commandline_args=("$@")

my_function

Dovete accedere agli argomenti della riga di comando tramite la commandline_argsvariabile, senza $@, $1, $2, ecc, ma sono a disposizione. Non sono a conoscenza di alcun modo per assegnare direttamente all'array di argomenti, ma se qualcuno ne conosce uno, per favore illuminami!

Inoltre, nota il modo in cui ho usato e citato $@: questo è il modo in cui assicuri che i caratteri speciali (spazi bianchi) non vengano confusi.


6
# Save the script arguments
SCRIPT_NAME=$0
ARG_1=$1
ARGS_ALL=$*

function stuff {
  # use script args via the variables you saved
  # or the function args via $
  echo $0 $*
} 


# Call the function with arguments
stuff 1 2 3 4

2

Si può fare anche così

#!/bin/bash
# script_name function_test.sh
function argument(){
for i in $@;do
    echo $i
done;
}
argument $@

Ora chiama il tuo script come

./function_test.sh argument1 argument2

function print() {è un amalgama tra due diversi moduli di dichiarazione di funzione - function print {, che è la sintassi legacy ksh che bash supporta per la compatibilità all'indietro con ksh pre-POSIX (vale a dire, pre-1991) e print() {, che è standardizzato da POSIX. Considera di utilizzare l'uno o l'altro per una maggiore compatibilità con altre shell; vedi anche wiki.bash-hackers.org/scripting/obsolete
Charles Duffy

1

È possibile utilizzare la parola chiave shift (operatore?) Per iterarli. Esempio:

#!/bin/bash
function print()
{
    while [ $# -gt 0 ]
    do
        echo $1;
        shift 1;
    done
}
print $*;

2
function print() {è un amalgama tra due diversi moduli di dichiarazione di funzione - function print {, che è la sintassi legacy ksh che bash supporta per la compatibilità all'indietro con ksh pre-POSIX (vale a dire, pre-1991) e print() {, che è standardizzato da POSIX. Considera di utilizzare l'uno o l'altro per una maggiore compatibilità con altre shell; vedi anche wiki.bash-hackers.org/scripting/obsolete
Charles Duffy

1

La mia soluzione:

Crea uno script di funzione che viene chiamato prima di tutte le altre funzioni senza passare alcun argomento, in questo modo:

! / bin / bash

funzione init () {ORIGOPT = "- $ @ -"}

Dopo di ciò, puoi chiamare init e usare la var ORIGOPT secondo necessità, come plus, assegno sempre una nuova var e copio il contenuto di ORIGOPT nelle mie nuove funzioni, in questo modo puoi assicurarti che nessuno la toccherà o cambiarlo.

Ho aggiunto spazi e trattini per renderlo più facile da analizzare con 'sed -E' inoltre bash non lo passerà come riferimento e farà crescere ORIGOPT quando le funzioni vengono chiamate con più argomenti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.