Bash, avviso senza argomenti e decisioni sui casi


110

Sto imparando bash.

Vorrei fare un semplice script che, quando non vengono forniti argomenti, mostri un messaggio. E quando fornisco numeri come argomento, a seconda del valore, fa una cosa o un'altra.

Vorrei anche sapere suggerimenti per i migliori manuali online per principianti in bash

Grazie

Risposte:


176
if [[ $# -eq 0 ]] ; then
    echo 'some message'
    exit 0
fi

case "$1" in
    1) echo 'you gave 1' ;;
    *) echo 'you gave something else' ;;
esac

La Advanced Bash-Scripting Guide è piuttosto buona. Nonostante il suo nome, tratta le basi.


RE: "uscita 0". Non so se uscire dalla sceneggiatura fosse quello che aveva in mente. Ma sì, è un'ottima guida.
Trampas Kirk

Ho interpretato "e" come "altrimenti", assumendo che il messaggio fosse un testo di aiuto. Ma sono sicuro che Werner è in grado di capire cosa fa quella linea e se lo vuole :)
Thomas

grazie, ovviamente! e ultima cosa, come posso disattivare i messaggi di errore nello script, in modo che non vengano mostrati alla shell?
Apri la strada

Intendi gli errori che vengono da un particolare programma che stai chiamando? È possibile inserire > /dev/nulle / o 2> /dev/nulldopo per inviare il suo output standard e / o flussi di errore standard nell'oblio.
Thomas

4
Se consideri un argomento mancante qualcosa di sbagliato (come lo script non può essere eseguito correttamente), restituisci qualcosa di diverso da 0 ( exit 1). Esistono ulteriori convenzioni sui codici di ritorno / uscita, che puoi trovare rapidamente online, ma il punto importante è che non dovrebbe essere 0, che indica il successo.
Felix

25

Se sei interessato solo al salvataggio se manca un particolare argomento, la sostituzione dei parametri è ottima:

#!/bin/bash
# usage-message.sh

: ${1?"Usage: $0 ARGUMENT"}
#  Script exits here if command-line parameter absent,
#+ with following error message.
#    usage-message.sh: 1: Usage: usage-message.sh ARGUMENT

11

Esempio

 if [ -z "$*" ]; then echo "No args"; fi

Risultato

No args

Dettagli

-z è l'operatore unario per la lunghezza della stringa è zero. $*sono tutti argomenti. Le virgolette sono per sicurezza e incapsulano più argomenti se presenti.

Usa man bashe cerca ( / key) "unario" per più operatori come questo.


7
Un (minore) problema con questo è che non fa distinzione tra non passare argomenti e passare una stringa vuota come argomento. Ciò può essere importante in alcuni contesti. Usando [$ # -eq 0] si possono gestire correttamente entrambi i casi.
Idelic

1
Ah, le sottigliezze della programmazione (ba) sh ... Questo è il motivo per cui lo odio.
Thomas

1
pensare a -zcome mizzing
Ray Foss

4

Vecchia ma ho motivo di rielaborare la risposta ora grazie a qualche precedente confusione:

if [[ $1 == "" ]] #Where "$1" is the positional argument you want to validate 

 then
 echo "something"
 exit 0

fi

Questo farà eco "Qualcosa" se non c'è un argomento posizionale $ 1. Tuttavia, non convalida che $ 1 contenga informazioni specifiche.


$#è esplicitamente il conteggio intero del numero di argomenti; o sarà "0", e farai l'eco di "qualcosa" anche se non ci sono argomenti, oppure sarà un numero positivo, e farai l'eco di "qualcosa" correttamente. Ma il controllo stesso non farà mai nulla, indipendentemente dall'input o dalla mancanza di input che usi: segnalerà sempre che $#contiene un valore. Quindi questo è completamente sbagliato e non funzionerà mai come affermato.
eschwartz

Ne sei completamente positivo? Ho diversi script che funzionano come previsto utilizzando questo formato esatto. Dopo aver letto la tua risposta ho anche ritestato sia per la corrispondenza che per la sua mancanza. $ # non conterrà un valore se non specificato, se non ci sono argomenti posizionali per corrispondere a ciò che è mai # nel tuo scenario. Non ha senso il motivo per cui bash assume un valore in un argomento posizionale che non c'è.
Ryan Smith

Prova echo $#come contenuto di uno script /tmp/test.sh, quindi eseguilo sotto / bin / bash così come / bin / sh (o / bin / dash e qualsiasi altra implementazione di shell che hai a disposizione. /tmp/test.shFarà eco "0" a la console, come farà /bin/dash /tmp/test.sh. D'altra parte, /tmp/test.sh foofarà eco "1" e /tmp/test.sh first secondfarà eco "2".
eschwartz

Come per man bash, nella sezione "Parametri speciali", "La shell tratta diversi parametri in modo speciale. Questi parametri possono solo essere referenziati; l'assegnazione ad essi non è consentita.", E "# Si espande al numero di parametri posizionali in decimale." Allo stesso modo è imposto
eschwartz

Sembra che ci sia stato un errore di comunicazione! Intendevo # come segnaposto per l'argomento posizionale specifico (cioè $ 2 se intendevi il secondo argomento) non letterale $ #. Dopo aver esaminato quanto sopra, hai assolutamente ragione, un $ # letterale risolverà sempre il numero di argomenti. Mi scuso per la confusione.
Ryan Smith
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.