bash kabuğundaki birden çok satırda durum varsa


19

Bir argüman alır ve gerekirse bir şey gerçekleştirmek bir bash kabuk işlevi var.

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

Bu yöntemi birkaç argümanla çağırmak ve bunlardan en az birinin başarılı olup olmadığını kontrol etmek istiyorum.

Gibi bir şey denedim:

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

Bunun için doğru sözdizimi ne olacak?
EDIT
Ayrıca - İlk koşul doğru olsa bile diğer tüm koşulların hala değerlendirileceğinden emin olmak istiyorum.

Teşekkürler,


Cevabımı güncelledim.
tectux

Teşekkürler, lütfen bir örnek verebilir misiniz?
Itay

1
Cevabıma bir kod örneği ekledim.
tectux

Yanıtlar:


7

Önce komutları çalıştırın, sonra bunlardan en az birinin başarılı olup olmadığını kontrol edin.

#!/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
Bu kafa karıştırıcıdır, koşullu ifadelerin bash'da nasıl çalıştığına dair bazı açıklamalar sağlayabilirseniz sevinirim ..., do_something başarı üzerine 0 döndürür, ancak daha sonra başarıyı 1 olarak güncelleriz ..., if ((success))farklı bir şeyi değerlendiririz if success. Kafam karıştı :)
Itay

2
@Itay ((...))aritmetik bir komuttur. İçerideki sonuç sıfırdan farklıysa true (0) döndürür. İçerideki sonuç 0 ise false (1) döndürür. "Başarı", bir sayı içermesini beklediği bir değişken olarak ele alınır. Bkz. Mywiki.wooledge.org/AritmetikExpression
geirha

Teşekkürler, sanırım beni karıştıran kısım 0 doğru ve 1 yanlış genellikle tersidir :)
Itay

2
@Itay Evet, ilk başta kafa karıştırıcı olabilir. Bash genel amaçlı dillerden farklıdır, çünkü "komut tabanlı"; işlevleri çağırmaz, sınıfları ve yöntemleri yoktur, komutları çalıştırır ve komutların çıkış durumlarını test eder. Ve komutları bash'de C, python, java, perl, vb.Gibi dillerden çalıştırmak çok daha kolaydır. Komutlar, başarıyı göstermek için 0 ve çeşitli hata türleri için 1-255 ile çıkar. (Bir komut genellikle sadece bir şekilde başarılı olabilir, ancak çeşitli nedenlerden dolayı başarısız olabilir)
geirha

2
Bu çözüm, geçici olarak devre dışı bırakmak istemediğiniz satırları yorumlayabilme avantajına sahiptir
Josiah Yoder

31

Ters eğik çizgiler kullanın.

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

DÜZENLE

Ayrıca - İlk koşul doğru olsa bile diğer tüm koşulların hala değerlendirileceğinden emin olmak istiyorum.

Bu yalnızca bir if ifadesinde mümkün değildir. Bunun yerine, bağımsız değişkenler üzerinde yinelenen ve bunları ayrı ayrı değerlendiren bir for döngüsü kullanabilirsiniz. Gibi bir şey:

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
}

teşekkürler, denedim - bir hata alıyorum[: do_something: unary operator expected
Itay

Her bir değerlendirmeyi kendi parantezleri arasına mı koydunuz? Bunun [ expr1 ] || [ expr2 ]yerine [ expr1 || expr2 ].
tectux

evet, yaptım: (...
Itay

Benim tahminim, do_something "arg1"iki argüman olarak yorumlanırken ifade tek olmalıdır. Yapmanın herhangi bir yolu do_something "arg1"bir argüman olarak değerlendirilebilir mi?
Itay

1
Haklısın. Bu da çalışır: if [ $(do_something "arg1") ].
tectux

5

Doğru sözdizimi:

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

\ kabukta bir sonraki satırda bir komutun devam ettiğini söylemek için kullanılır.

EDIT : Bence bu istediğini yapmak gerekir:

#!/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"

Teşekkürler, bir hata ile sonuçlanır:[: too many arguments
Itay

@Itay Yanıt güncellendi.
Eric Carvalho

Soruyu güncellemek - bu henüz son cevap değil :(
Itay

-1

Tercih ederim:

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

Senaryo hiç çalışmaz: 1. test parametresinden sonra, bir \nkarakter ifüretecektir do_something, bu nedenle
ifadeniz

Benim için zsh ve bash'da çalışıyor, IF do_somethingelbette bir işlev. do_somethingişlev veya komut olmalı, başka ne olmalı? Ayrıca \nsonucu yankılanan dışında bir karakter nerede üreteceğini görmüyorum ve bu bekleniyor ...
Toxiro
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.