Bash'te basit mantıksal operatörler


256

Birkaç değişkenim var ve aşağıdaki koşulu (kelimelerle yazılmış, sonra bash komut dosyasında başarısız denememi) kontrol etmek istiyorum:

if varA EQUALS 1 AND ( varB EQUALS "t1" OR varB EQUALS "t2" ) then 

do something

done.

Başarısız denememle birlikte:

if (($varA == 1)) && ( (($varB == "t1")) || (($varC == "t2")) ); 
  then
    scale=0.05
  fi

Yanıtlar:


682

Yazdıklarınız neredeyse işe yarıyor (tüm değişkenler sayı olsaydı işe yarardı), ama bu deyimsel bir yol değil.

  • (…)parantezler bir alt kabuğu gösterir . İçlerindeki şey, diğer birçok dilde olduğu gibi bir ifade değildir. Komutların bir listesi (tıpkı dış parantezler gibi). Bu komutlar ayrı bir alt işlemde yürütülür, bu nedenle parantez içinde yapılan yeniden yönlendirme, atama vb. Parantezlerin dışında bir etkiye sahip değildir.
    • Başında dolar işareti $(…)olan bir komut ikamesi vardır : parantez içinde bir komut vardır ve komuttan çıktı komut satırının bir parçası olarak kullanılır (ikame çift tırnak işaretleri arasında olmadığı sürece ekstra genişletmelerden sonra, ancak bu başka bir hikaye ) .
  • { … }parantezler komutları grupladıkları için parantez gibidir, ancak gruplamayı değil ayrıştırmayı etkilerler. Program x=2; { x=4; }; echo $x4 yazdırır, oysa 2 x=2; (x=4); echo $xyazdırır.
    • Önde gelen dolar işareti ile, olası ekstra dönüşümlerle birlikte bir değişkenin değerine genişleyen ${VAR}bir parametre genişletmesidir .
  • ((…))çift ​​parantez , diğer programlama dillerine benzeyen bir sözdizimiyle aritmetik bir komutu , yani tamsayıları hesaplar. Bu sözdizimi çoğunlukla ödevler ve şartlar için kullanılır.
    • Aynı sözdizimi, ifadenin $((…))tamsayı değerine genişleyen aritmetik ifadelerde kullanılır .
  • [[ … ]]çift ​​parantez, koşullu ifadeleri çevreler . Koşullu ifadeler çoğunlukla bir değişkenin boş olup olmadığını sınama ve bir dosyanın var olup olmadığını sınama gibi işleçler üzerine kurulur. : String eşitlik operatörleri de vardır (sağ taraftaki bir desen, örneğin olduğunu dikkat testleri eğer ile başlar iken testler ise tam olarak ), ve tanıdık , ve olumsuzluk, birlikte ve ayrılmalara yanı sıra gruplama için parantez için operatörler. Not Her operatör (örneğin etrafında bir alanına ihtiyaç duyduğunu değil ) ve bir boşluk ya da benzeri bir karakter hem iç hem dış parantez (örneğin , değil-n $variable-e $file"$string1" == "$string2"[[ $foo == a* ]]$fooa[[ $foo == "a*" ]]$fooa*!&&||[[ "$x" == "$y" ]][[ "$x"=="$y" ]];[[ -n $foo ]][[-n $foo]]).
  • [ … ]tek parantez daha fazla tuhaf (ama daha eski ve daha taşınabilir) ile koşullu ifadelerin alternatif bir şeklidir. Şimdilik bir şey yazma; bunları içeren komut dosyaları bulduğunuzda endişelenmeye başlayın.

Testinizi bash'da yazmanın deyimsel yolu:

if [[ $varA == 1 && ($varB == "t1" || $varC == "t2") ]]; then

Diğer kabuklara taşınabilirliğe ihtiyacınız varsa, bu yol olacaktır (her bir testin etrafındaki ek alıntıları ve ayrı parantez setlerini =ve ksh / bash / zsh ==varyantı yerine geleneksel operatörün kullanımını not edin ):

if [ "$varA" = 1 ] && { [ "$varB" = "t1" ] || [ "$varC" = "t2" ]; }; then

31
Büyük yazı, parantez özeti sadece idealdir.
KomodoDave

10
==Karşılaştırmayı bir değişken (aynı zamanda =) atamaktan ayırt etmek daha iyidir
Will Sheppard

1
Oh, tek (yuvarlak) parantezler demek istedim, karışıklık için özür dilerim. [[ $varA = 1 && ($varB = "t1" || $varC = "t2") ]]İlk mermi noktası açıkça şunu söylese de, olanlar bir alt işleme başlamıyor: "[Parantez] içinde ne var , birçok dilde olduğu gibi bir ifade değil " - ama kesinlikle burada! Muhtemelen deneyimli bash wiz için açıktır, ama hemen benim için bile değil. Tek parantez çünkü karışıklık ortaya çıkabilir edilebilir bir kullanılan ifadil değil çift parantez içindeki ifadelerde, açıklamada.
Peter - Monica'yı yeniden

2
@protagonist ==gerçekte “daha ​​deyimsel” değildir =. Aynı anlama sahiptirler, ancak ==bash ve zsh'da da bulunan bir ksh varyantıdır, oysa =taşınabilirdir. Kullanmanın gerçekten bir avantajı ==yoktur ve düz sh'de çalışmaz.
Gilles 'SO- kötü olmayı bırak

2
@WillSheppard Karşılaştırma ve atama arasında başka birçok fark var: Karşılaştırma parantez içinde, atama değil; karşılaştırmanın operatör çevresinde boşlukları vardır, atama yoktur; atamanın solda değişken bir adı vardır, karşılaştırma nadiren solda değişken bir ada benzeyen bir şeye sahiptir ve yine de tırnak işaretleri koyabilirsiniz. İsterseniz ==içeride yazabilirsiniz [[ … ]], ancak =çalışma avantajı da vardır [ … ], bu yüzden kullanma alışkanlığına girmemenizi tavsiye ederim ==.
Gilles 'SO- kötü olmayı bırak

34

çok yakın

if [[ $varA -eq 1 ]] && [[ $varB == 't1' || $varC == 't2' ]]; 
  then 
    scale=0.05
  fi

çalışmalı.

parçalamak

[[ $varA -eq 1 ]] 

bir tamsayı karşılaştırmasıdır.

$varB == 't1'

bir dize karşılaştırmasıdır. Aksi takdirde, karşılaştırmaları doğru bir şekilde gruplandırıyorum.

Çift köşeli parantezler bir Koşullu İfadeyi sınırlar. Ve aşağıdakileri iyi bir okuma olarak görüyorum: "(IBM) Demystify testi, [, [[, ((ve if-then-else”)


Sadece emin olmak için: Alıntı 't1'yapmak gereksiz, değil mi? Çift parantez içinde aritmetik talimatlar aksine, nerede Çünkü t1değişken olacağını, t1çift bir koşullu ifadede parantez sadece bir hazır dizedir. Yani, [[ $varB == 't1' ]]tam olarak aynı [[ $varB == t1 ]], değil mi?
Peter - Monica'yı yeniden

6

Çok taşınabilir bir versiyon (eski bourne kabuğuna bile):

if [ "$varA" = 1 -a \( "$varB" = "t1" -o "$varB" = "t2" \) ]
then    do-something
fi

Bu, [kabuk aroması ne olursa olsun, en fazla tek bir alt işlem yürütme ek sürecine sahiptir (bu işlemdir ).

Değiştir =ile -eqdeğişkenler sayısal değerler içeriyorsa, örneğin

  • 3 -eq 03 doğru, ama
  • 3 = 03yanlış. (dize karşılaştırması)

3

İf-then-else deyiminin kısa sürümünün kodu:

( [ $a -eq 1 ] || [ $b -eq 2 ] ) && echo "ok" || echo "nok"

Aşağıdakilere dikkat edin:

  1. ||ve &&koşul (yani yuvarlak parantezler arasında) mantıksal işlenenler (veya / ve) ise içindeki işlenenler

  2. ||ve &&eğer koşul başka bir anlama geliyorsa dışarıda işlenenler

Pratikte ifade şöyle diyor:

eğer (a = 1 veya b = 2) o zaman "tamam" başka "nok"


Parantez ( ... )bir alt kabuk oluşturur. { ... }Bunun yerine kaşlı ayraç kullanmak isteyebilir . Alt kabukta oluşturulan hiçbir durum arayanda görünmez.
Clint Pachl

0
if ([ $NUM1 == 1 ] || [ $NUM2 == 1 ]) && [ -z "$STR" ]
then
    echo STR is empty but should have a value.
fi
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.