Bash'te "if" ifadesi için "ve" operatörü


168

Web sitesi kapalı olup olmadığını kontrol etmek için basit bir Bash komut dosyası oluşturmaya çalışıyorum ve bir nedenle "ve" operatörü çalışmıyor:

#!/usr/bin/env bash

WEBSITE=domain.com
SUBJECT="$WEBSITE DOWN!"
EMAILID="an@email.com"
STATUS=$(curl -sI $WEBSITE | awk '/HTTP\/1.1/ { print $2 }')
STRING=$(curl -s $WEBSITE | grep -o "string_to_search")
VALUE="string_to_search"

if [ $STATUS -ne 200 ] && [[ "$STRING" != "$VALUE" ]]; then
    echo "Website: $WEBSITE is down, status code: '$STATUS' - $(date)" | mail -s "$SUBJECT" $EMAILID
fi

"-A" operatörü de çalışmaz:

if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]

Ayrıca ne zaman kullanacağınızı da bildirir misiniz?

  • tek ve çift köşeli ayraçlar
  • parantez

?


3
Lütfen neyin işe yaramadığı konusunda daha kesin bilgi verir misiniz? Belirli bir hata mesajınız mı var, yoksa beklenen çıktıyı sağlamıyor mu?
Julien Vivenot

Aslında "tekli operatör bekleniyordu" alıyordum bu yüzden alıntı yardımcı olur gibi görünüyor
HTF

-ayineleniyor. Bourne kabuğu tarzı ile kullanıldığında testkomutu, aka [, bunun anlamı and. Koşullu ifade olarak kullanıldığında bir dosyanın var olup olmadığını test eder. Evet kafa karıştırıcı, en iyi kaçınılması.
cdarke

Yanıtlar:


254

${STATUS}Boş olmadıkça sahip olduğunuz şey çalışmalıdır . Muhtemelen yapmak daha iyi olurdu:

if ! [ "${STATUS}" -eq 200 ] 2> /dev/null && [ "${STRING}" != "${VALUE}" ]; then

veya

if [ "${STATUS}" != 200 ] && [ "${STRING}" != "${VALUE}" ]; then

Söylemek zor, çünkü senaryonuzda neyin yanlış gittiğini bize tam olarak göstermediniz.

Kişisel görüş: asla kullanmayın [[. Önemli hata mesajlarını bastırır ve farklı kabuklara taşınabilir değildir.


2
Eğer STATUSboştur, @HTF kod başarısız olurdu -ne: unary operator expected. Senin durumunda, başarısız integer expression expectedolacak, değil mi?
Julien Vivenot

1
Onu anlıyorum. Ancak $STATUSboş olabilecek sorunu vurgular ve bir çözüm önerirsiniz (alıntı yaparak). Çözümünüz hala boş bir şeyle başarısız oluyor STATUS, demek istediğim bu.
Julien Vivenot

1
@jvivenot Bir noktan var. (Yorumunuza verdiğiniz yanıt, yorumunuzu düzenlemeden önce yapıldı, yorumunuz yalnızca "kod ... başarısız olurdu". Basit bir çözüm kullanmaktır ${STATUS:-0". Düzenleyecektir.
William Pursell

Maalesef, düzenlemeniz hala çalışmıyor. Örneğin: STATUS=; [ $STATUS -ne 13 ] 2>/dev/null && echo fooolması gerekse foobile çıktı vermez (boş 13'ten farklıdır). İlk önerdiğiniz şey ${STATUS:-0}çok daha iyi görünüyor.
Julien Vivenot

@jvivenot ${STATUS:-0}Eğer kullanılırsa başarısız olur STATUS=foo, ancak ! [ "$STATUS" -eq 200 ] 2> /dev/null && echo fooçalışır. IMO, kaçınmak -eqve kullanmak daha iyidir !=.
William Pursell

28

Bunu dene:

if [ $STATUS -ne 200 -a "$STRING" != "$VALUE" ]; then

benim için çalıştı. Bence birden fazla yol olabilir ama şimdilik bundan memnunum.
Kushal Ashok

27

Bunu dene:

if [ ${STATUS} -ne 100 -a "${STRING}" = "${VALUE}" ]

veya

if [ ${STATUS} -ne 100 ] && [ "${STRING}" = "${VALUE}" ]

en temiz örnek için
Pawel Cioch

12

Alıntı:

"-A" operatörü de çalışmaz:

[$ STATUS -ne 200] -a [["$ STRING"! = "$ VALUE"]]

Daha ayrıntılı bir açıklama için: [ve ]Bash'a ayrılmış kelimeler değildir. ifAnahtar kelime tanıttı koşullu bir iş tarafından değerlendirilecek (işin dönüş değeri ise koşullu doğrudur 0ya yanlış şekilde).

Önemsiz testler için testprogram ( man test) vardır.

Bazıları if test -f filename; then foo bar; fi, vb. Gibi sinir bozucu çizgiler bulduğunda , çoğu sistemde [aslında testprograma sadece bir sembolik bağlantı adı verilen bir program bulabilirsiniz . Ne zaman testolarak adlandırılır [, eklemek zorunda ]son pozisyonel argüman olarak.

Yani if test -f filenametemelde olarak (estiren süreçler açısından) aynıdır if [ -f filename ]. Her iki durumda da testprogram başlatılacak ve her iki süreç de aynı şekilde davranmalıdır.

İşte hatan: iş + kendisi hariç her şey + if [ $STATUS -ne 200 ] -a [[ "$STRING" != "$VALUE" ]]ayrışacak . İş sadece basit bir komuttur (Bash tek bir işlemle sonuçlanan bir şey için konuşur), yani ilk kelime ( ) komuttur ve geri kalanı konumsal argümanlarıdır. İlkinden sonra geriye kalan tartışmalar var .ifif[]

Ayrıca [[, gerçekten bir Bash anahtar kelimesidir, ancak bu durumda, yalnızca normal bir komut argümanı olarak ayrıştırılır, çünkü komutun önünde değildir.

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.