se condizione su più righe nella shell bash


19

Ho una funzione shell bash che accetta un argomento ed esegue qualcosa su di esso, se necessario.

do_somthing() {
  if [need to do something on $1]
  then
    do it
    return 0
  else
    return 1
  fi
}

Voglio chiamare questo metodo con diversi argomenti e verificare se almeno uno di essi è riuscito.

Ho provato qualcosa del tipo:

if [ do_something "arg1" ||
     do_something "arg2" ||
     do_something "arg3" ]
then
  echo "OK"
else
  echo "NOT OK"
fi

Quale sarà la sintassi corretta per questo?
EDIT
Inoltre - Voglio assicurarmi che anche se la prima condizione è vera, tutte le altre condizioni saranno comunque valutate.

Grazie,


Ho aggiornato la mia risposta.
tectux,

Grazie, puoi fornire un esempio?
Itay,

1
Ho aggiunto un esempio di codice alla mia risposta.
tectux,

Risposte:


7

Esegui prima i comandi, quindi controlla se almeno uno di essi è riuscito.

#!/bin/bash

success=0
do_something arg1 && success=1
do_something arg2 && success=1
do_something arg3 && success=1

if ((success)); then
    printf 'Success! At least one of the three commands succeeded\n'
fi

3
Questo è confuso, sarò felice se tu potessi fornire qualche spiegazione su come funzionano le istruzioni condizionali in bash ..., do_something restituisce 0 in caso di successo, ma poi aggiorniamo il successo in 1 ..., if ((success))valuta qualcosa di diverso da if success. Sono confuso :)
Itay,

2
@Itay ((...))è un comando aritmetico. Se il risultato all'interno è diverso da zero, restituisce true (0). Se il risultato all'interno è 0, restituisce false (1). "successo" viene trattato come una variabile che prevede di contenere un numero. Vedi mywiki.wooledge.org/ArithmeticExpression
geirha

Grazie, suppongo che la parte che mi ha confuso sia che 0 è vero e 1 è falso di solito è l'opposto :)
Itay

2
@Itay Sì, all'inizio potrebbe essere fonte di confusione. Bash differisce dai linguaggi di uso generale in quanto è "basato sui comandi"; non chiama funzioni, non ha classi e metodi, esegue comandi e verifica gli stati di uscita dei comandi. Ed è molto più semplice eseguire comandi in bash rispetto a linguaggi come C, python, java, perl, ecc. I comandi escono con 0 per segnalare il successo e 1-255 per vari tipi di errori. (Un comando può generalmente riuscire solo in un modo, ma fallisce per vari motivi diversi)
geirha,

2
Questa soluzione ha il vantaggio di poter commentare le righe che non si desidera disattivare temporaneamente
Josiah Yoder,

31

Usa le barre rovesciate.

if [ $(do_something "arg1") ] || \
   [ $(do_something "arg2") ] || \
   [ $(do_something "arg3") ]
then
  echo "OK"
else
  echo "NOT OK"
fi

MODIFICARE

Inoltre, voglio assicurarmi che anche se la prima condizione è vera, tutte le altre condizioni saranno comunque valutate.

Questo non è possibile in una sola istruzione if. Invece puoi usare un ciclo for che scorre gli argomenti e li valuta separatamente. Qualcosa di simile a:

do_something() {
  for x in "$@"
  do
    if [need to do something on $x]
    then
      do it
    else
      echo "no action required on $x"
    fi
  done
}

grazie, l'ho provato - ho ricevuto un errore[: do_something: unary operator expected
Itay,

Hai inserito ciascuna valutazione tra parentesi? Quindi [ expr1 ] || [ expr2 ]invece di [ expr1 || expr2 ].
tectux,

si, ho fatto: (...
Itay,

La mia ipotesi è che do_something "arg1"sia interpretato come due argomenti mentre l'espressione dovrebbe essere unaria. Qualche modo di fare può do_something "arg1"essere valutato come un argomento?
Itay,

1
Hai ragione. Questo funziona anche: if [ $(do_something "arg1") ].
tectux,

5

La sintassi corretta è:

if  do_something "arg1" || \
    do_something "arg2" || \
    do_something "arg3"
then
  echo "OK"
else
  echo "NOT OK"
fi

\ è usato per dire alla shell che un comando continua nella riga successiva.

EDIT : penso che questo dovrebbe fare quello che vuoi:

#!/bin/bash

do_something() {
  if [need to do something on $1]
  then
    do it
    echo "OK"
  else
    echo "NOT OK"
  fi
}

do_something "arg1"
do_something "arg2"
do_something "arg3"

Grazie, risultati con un errore:[: too many arguments
Itay,

@Itay Risposta aggiornata.
Eric Carvalho,

Aggiornamento della domanda: questa non è ancora la risposta finale :(
Itay,

-1

Preferisco:

if {
    do_something "arg1" ||
    do_something "arg2" ||
    do_something "arg3"
}; then
    echo "OK"
else
    echo "NOT OK"
fi

Lo script non funzionerà affatto: dopo il primo parametro di test, genererebbe un \ncarattere, quindi la tua ifistruzione genererebbe alcuni errori e do_somethingnon sono nomi di comandi, quindi più errori
damadam

Per me funziona in zsh e bash, IF do_somethingè una funzione ovviamente. do_somethingdeve essere funzione o comando, cos'altro dovrebbe essere? Inoltre non vedo dove genererebbe un \npersonaggio se non dopo aver fatto eco al risultato e questo è previsto ...
Toxiro
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.