Qual è la sintassi di una condizione complessa nella shell?


10

Se vuoi esprimere il seguente test in shell (sh):

if ( a == 1 && ( b == 1 || b == 2 )) { ... }

Finora, il migliore che ho potuto scrivere è questo:

if [[ $a -eq 1 ]]; then
  if [[ $b -eq 1 || $b -eq 2 ]]; then
     ...
  fi
fi

Non so come combinare && e || con la precedenza corretta. Google non mi ha dato alcuna risposta (i tutorial forniscono solo esempi di base, se presenti)

Qual è la sintassi per combinare quei due se in uno?


1
Qualche motivo per non usarlo ksh? Quindi il tuo codice iniziale richiederebbe solo un'altra coppia di parentesi:if (( a == 1 && ( b == 1 || b == 2 ))); then :; fi
manat

Risposte:


14

Si noti che [[ ]]non è in Bourne o POSIX sh. Per la vera shsintassi, ci sono diversi modi per farlo.

Utilizzando solo una [ ]coppia

if [ 1 -eq "$a" -a \( 1 -eq "$b" -o 2 -eq "$b" \) ]; then
    # ...
fi

o Evitare POSIX -ae le -oopzioni 1

if [ 1 -eq "$a" ] && { [ 1 -eq "$b" ] || [ 2 -eq "$b" ]; }; then
    # ...
fi

1 Un motivo per evitare -aed -oè la massima portabilità: non tutte testo le [implementazioni sono in grado di gestire più di 4 argomenti, che è esattamente ciò che si ottiene se si concatenano espressioni con -ae -oe \( \).


I miei script hanno il #! / bin / sh shebang e la shell predefinita è ksh . Perché sh non dovrebbe essere usato?
Offirmo,

2
@Offirmo Se si dichiara lo script come /bin/sh, non è corretto scrivere lo script utilizzando funzionalità non presenti sh. Dovresti essere consapevole che kshNON è sh, ma piuttosto un superset di sh. Se kshporti il tuo -but-dichiarato-come- shscript a un sistema in cui shnon è presente un collegamento simbolico ksh, potrebbe interrompersi. Puoi evitare questo problema assicurandoti che lo script corrisponda alla dichiarazione.
jw013,

Ho pensato che l'impostazione / bin / sh come shebang avrebbe fatto invocare i miei script tramite / bin / sh . Vuoi dire che la mia shell predefinita (ksh) ignora lo shebang e lo interpreta direttamente?
Offirmo,

@Offirmo Hai ragione: /bin/shinvoca una shebang di /bin/sh. Il problema è /bin/shche non accetta [[. Non puoi usare [[o usare una shell che accetta [[, ad esempio ksh, come shebang.
jw013,

2
Il problema non è tanto che -a/ -onon sono supportate da alcune implementazioni ma che non è affidabile per argomenti arbitrari. Like [ "$a" = "$b" -o "$b" = "$c" ]fallirebbe per valori di $alike !con molte [implementazioni.
Stéphane Chazelas,

2

Ho provato un po 'di sintassi e l'ho trovato

if [[ $a -eq 1 ]] && [[ $b -eq 1 || $b -eq 2 ]]; then
 ...
fi

sta lavorando.


1
funziona per la versione bash sopra 4.
Nikhil Mulley


0

Il modo giusto di farlo con un semplice shell:

if test 1 -eq "$a" && test 1 -eq "$b" -o 2 -eq "$b"; then 
    ...
fi

Spiegazione:

testqui serve come parentesi e -ocome logico o. Se fosse una logica e dentro la "parentesi" useresti -a.

Maggiori informazioni su questo possono essere trovate qui

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.