Parametri di script in Bash


103

Sto cercando di creare uno script di shell che dovrebbe essere usato in questo modo:

ocrscript.sh -from /home/kristoffer/test.png -to /home/kristoffer/test.txt

Lo script convertirà quindi il file immagine in un file di testo. Ecco cosa ho trovato finora:

#!/bin/bash
export HOME=/home/kristoffer
/usr/local/bin/abbyyocr9 -rl Swedish -if ???fromvalue??? -of ???tovalue??? 2>&1

Ma non so come ottenere i valori -frome -to. Qualche idea su come farlo?


Risposte:


124

Gli argomenti che forniti dall'utente a un bashscript appariranno nelle variabili $1ed $2e $3dove il numero si riferisce all'argomento. $0è il comando stesso.

Gli argomenti sono separati da spazi, quindi se fornisci il -frome -tonel comando, finiranno anche in queste variabili, quindi per questo:

./ocrscript.sh -from /home/kristoffer/test.png -to /home/kristoffer/test.txt

Otterrai:

$0    # ocrscript.sh
$1    # -from
$2    # /home/kristoffer/test.png
$3    # -to
$4    # /home/kristoffer/test.txt

Potrebbe essere più facile omettere il -frome il -to, come:

ocrscript.sh /home/kristoffer/test.png /home/kristoffer/test.txt

Allora avrai:

$1    # /home/kristoffer/test.png
$2    # /home/kristoffer/test.txt

Lo svantaggio è che dovrai fornirlo nell'ordine giusto. Esistono librerie che possono semplificare l'analisi degli argomenti con nome sulla riga di comando, ma di solito per semplici script di shell dovresti semplicemente usare il modo semplice, se non c'è problema.

Quindi puoi fare:

/usr/local/bin/abbyyocr9 -rl Swedish -if "$1" -of "$2" 2>&1

Le virgolette doppie attorno a $1e $2non sono sempre necessarie ma sono consigliate, perché alcune stringhe non funzioneranno se non le mettete tra virgolette doppie.


69

Se non sei completamente attaccato all'utilizzo di "da" e "a" come nomi di opzione, è abbastanza facile implementarlo usando getopts :

while getopts f:t: opts; do
   case ${opts} in
      f) FROM_VAL=${OPTARG} ;;
      t) TO_VAL=${OPTARG} ;;
   esac
done

getopts è un programma che elabora gli argomenti della riga di comando e li analizza convenientemente per te.

f:t:specifica che ti aspetti 2 parametri che contengono valori (indicati dai due punti). Qualcosa di simile f:t:vdice che -vsarà interpretato solo come una bandiera.

optsè dove è memorizzato il parametro corrente. La casedichiarazione è dove elaborerai questo.

${OPTARG}contiene il valore che segue il parametro. ${FROM_VAL}per esempio otterrà il valore /home/kristoffer/test.pngse hai eseguito lo script come:

ocrscript.sh -f /home/kristoffer/test.png -t /home/kristoffer/test.txt

Come suggeriscono gli altri, se è la prima volta che scrivi script bash, dovresti davvero leggere alcune nozioni di base. Questo era solo un breve tutorial su come getoptsfunziona.


1
Questa sembra essere una soluzione leggibile. Come specifichereste quindi due flag?
Zelphir Kaltstahl

@Zelphir, puoi specificare due o più flag semplicemente omettendo il ":" dopo il flag. Ad esempio f:t:vssarà-f some_f -t some_t -v -s
h_s

34

Utilizzare le variabili "$1", "$2", "$3"e così via per gli argomenti di accesso. Per accedere a tutti è possibile utilizzare "$@"o per ottenere il conteggio degli argomenti $#(potrebbe essere utile per verificare la presenza di troppi o troppo pochi argomenti).


24

Avevo bisogno di assicurarmi che i miei script fossero completamente portabili tra varie macchine, shell e persino versioni di cygwin. Inoltre, i miei colleghi che erano quelli per cui ho dovuto scrivere gli script, sono programmatori, quindi ho finito per usare questo:

for ((i=1;i<=$#;i++)); 
do

    if [ ${!i} = "-s" ] 
    then ((i++)) 
        var1=${!i};

    elif [ ${!i} = "-log" ];
    then ((i++)) 
        logFile=${!i};  

    elif [ ${!i} = "-x" ];
    then ((i++)) 
        var2=${!i};    

    elif [ ${!i} = "-p" ]; 
    then ((i++)) 
        var3=${!i};

    elif [ ${!i} = "-b" ];
    then ((i++)) 
        var4=${!i};

    elif [ ${!i} = "-l" ];
    then ((i++)) 
        var5=${!i}; 

    elif [ ${!i} = "-a" ];
    then ((i++)) 
        var6=${!i};
    fi

done;

Motivazione: ho incluso anche uno launcher.shscript, poiché l'intera operazione prevedeva diversi passaggi quasi indipendenti l'uno dall'altro (sto dicendo "quasi", perché anche se ogni script poteva essere eseguito da solo, di solito venivano eseguiti tutti insieme ), e in due giorni ho scoperto che circa la metà dei miei colleghi, essendo programmatori e tutti, era troppo brava per usare il file di avvio, seguire l '"utilizzo" o leggere la GUIDA che veniva visualizzata ogni volta che facevano qualcosa sbagliato e stavano facendo un pasticcio, eseguendo script con argomenti nell'ordine sbagliato e lamentandosi del fatto che gli script non funzionavano correttamente. Essendo il collerico che sono, ho deciso di rivedere tutti i miei script per assicurarmi che fossero a prova di collega. Il segmento di codice sopra è stata la prima cosa.


2
Mi piace questo. Sto aggiungendo una sezione alla fine `else echo" Argomento non valido: $ {! I} "((i ++))
fi`

6

In bash $1è il primo argomento passato allo script, il $2secondo e così via

/usr/local/bin/abbyyocr9 -rl Swedish -if "$1" -of "$2" 2>&1

Quindi puoi usare:

./your_script.sh some_source_file.png destination_file.txt

Spiegazione sulle virgolette doppie;

considera tre script:

# foo.sh
bash bar.sh $1

# cat foo2.sh
bash bar.sh "$1"

# bar.sh
echo "1-$1" "2-$2"

Ora invoca:

$ bash foo.sh "a b"
1-a 2-b

$ bash foo2.sh "a b"
1-a b 2-

Quando invocate foo.sh "a b", invoca bar.sh a b(due argomenti) e con foo2.sh "a b"esso invoca bar.sh "a b"(1 argomento). Tieni sempre a mente come i parametri vengono passati ed espansi in bash, ti farà risparmiare un sacco di mal di testa.

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.