2010-04-15 13 views
18

Ci sono una serie di domande su questo genere di cose ma immaginiamo di prendere di mira un sistema Linux generico con getopt e getopts installati (non che useremo entrambi, ma sembrano popolari)Argomento dello script di shell parsing

Come effettuo il parsing entrambi i lunghi | argruments (--example --example semplice opzione) e brevi (-e | -esimple-example | -e semplice esempio)

risposta

33

Si desidera utilizzare getopt con lunghi e opzioni brevi. Un esempio dal codice di lavoro:

# Parse arguments 
TEMP=$(getopt -n $PROGRAM_NAME -o p:P:cCkhnvVS \ 
--long domain-password:,pop3-password:\   
,create,cron,kill,help,no-sync-passwords,version,verbose,skip-pop3 \ 
-- "[email protected]")                

# Die if they fat finger arguments, this program will be run as root 
[ $? = 0 ] || die "Error parsing arguments. Try $PROGRAM_NAME --help"  

eval set -- "$TEMP" 
while true; do  
     case $1 in 
       -c|--create) 
         MODE="CREATE"; shift; continue 
       ;;          
       -C|--cron)        
         MODE="CRON"; shift; continue 
       ;;          
       -k|--kill)        
         MODE="KILL"; shift; continue 
       ;;          
       -h|--help)        
         usage       
         exit 0       
       ;;          
       -n|--no-sync-passwords)    
         SYNC_VHOST=0; shift; continue 
       ;;          
       -p|--domain-password)     
         DOMAIN_PASS="$2"; shift; shift; continue 
       ;;            
       -P|--pop3-password)        
         POP3_PASS="$2"; shift; shift; continue 
       ;;            
       -v|--version)         
         printf "%s, version %s\n" "$PROGRAM_NAME" "$PROGRAM_VERSION" 
         exit 0              
       ;;                 
       -v|--verbose)              
         VERBOSE=1; shift; continue         
       ;;                 
       -S|--skip-pop3)              
         SKIP_POP=1; shift; continue         
       ;;                 
       --)                 
         # no more arguments to parse         
         break              
       ;;                 
       *)                 
         printf "Unknown option %s\n" "$1"       
         exit 1              
       ;;                 
     esac                   
done  

nota, die è una funzione che è stata definita in precedenza (non mostrato).

L'opzione -n indica a getopt di segnalare errori come nome del mio programma, non come getopt. -o definisce un elenco di opzioni brevi (: dopo che un'opzione indica un argomento necessario) e --long specifica l'elenco di opzioni lunghe (corrispondenti per le opzioni brevi).

Il resto è solo un semplice interruttore, che chiama shift in modo appropriato per far avanzare il puntatore argomento. Nota, chiamare shift; shift; è solo una dura abitudine. Nel mondo attuale, probabilmente shift 2 sarebbe sufficiente.

Il getopt moderno è piuttosto coerente rispetto alle piattaforme più recenti, tuttavia è possibile che si verifichino problemi di portabilità su sistemi precedenti (circa pre-RedHat 9). Vedere man getopt per informazioni sulla compatibilità con le versioni precedenti. Tuttavia è improbabile che ti imbatti nel bisogno di farlo.

Infine, dopo le opzioni di analisi, si può ancora una volta chiamare:

eval set -- "[email protected]" 

Questo sarà spostare il puntatore argomento a qualsiasi altra cosa a sinistra sulla riga di comando dopo getopt è stato fatto opzioni di analisi. Puoi quindi semplicemente shift continuare a leggerli. Per esempio, se un comando si presentava così:

./foo --option bar file1.txt file2.txt file3.txt 

Non dimenticare di fare un pratico -h/--help opzione per stampare le nuove opzioni di fantasia una volta il gioco è fatto. :) Se rendi tale output help2man amichevole, hai una pagina man istantanea da usare con il tuo nuovo strumento.

Modifica

Sulla maggior parte delle distribuzioni, è possibile trovare ulteriori esempio getopt codice /usr/share/doc/util-linux/examples, che avrebbe dovuto essere installato di default.

+0

Mi rendo conto che non sto facendo di sanità mentale per verificare l'impostazione di più comandi MODE. In questo caso, era accettabile che l'ultima opzione avesse semplicemente la precedenza, e l'incolla era pensata solo per essere informativo su un modo di usare 'getopt'. –

+0

Mi è stato riferito di usare 'getopt()' diverse volte ora. Chiamami stupido, ma non riesco a capire come funziona. Dal momento che il mio script aveva bisogno di un equivalente di Windows, io [ho usato questo] (http://stackoverflow.com/a/3981086/314056). Secondo me, è un approccio molto più pulito e meno magico. Posso fare qualcosa di simile su Linux? – Christian

+0

@Christian Potresti avere qualcosa di simile con BASH, '% 1' diventando' $ 1' (e '$ 2' rispettivamente se' $ 1' si aspetta un argomento). In effetti, molte persone lo fanno in questo modo, continuano a scorrere gli argomenti tramite 'shift' e eseguendo l'argomento corrente tramite un interruttore.'getopt' semplicemente gestisce tutta questa magia, oltre a un controllo obbligatorio degli argomenti per te, così tanti come questa comodità. –

Problemi correlati