Bash dizeleri nasıl karşılaştırılır


Yanıtlar:


1374

İf ifadelerinde değişkenler kullanma

if [ "$x" = "valid" ]; then
  echo "x has the value 'valid'"
fi

Eğer onlar eşleşmeyen bir şey yapmak istiyorsanız, yerini =ile !=. Dizge işlemleri ve aritmetik işlemler hakkında daha fazla bilgiyi ilgili dokümanlarda bulabilirsiniz.

Neden tırnak işaretleri kullanıyoruz $x?

Tırnakların etrafında olmasını istiyorsunuz $x, çünkü boşsa, Bash betiğiniz aşağıda görüldüğü gibi bir sözdizimi hatasıyla karşılaşır:

if [ = "valid" ]; then

==Operatörün standart dışı kullanımı

Bash'in ==eşitlik için kullanılmasına izin verdiğini unutmayın [, ancak bu standart değildir .

Tırnakların $xisteğe bağlı olduğu ilk durumu kullanın :

if [[ "$x" == "valid" ]]; then

veya ikinci vakayı kullanın:

if [ "$x" = "valid" ]; then

12
Bu, Beklenmedik operatör hatası sırasında verilen kabul edilen yanıtla nasıl bir bağlantıdır ? Kullanırken aynı hatayı aldım [ "$1" == "on" ]. Bunu ["$ 1" = "on"] olarak değiştirmek sorunu çözdü.
Piotr Dobrogost

78
Alanlara ihtiyaç var.
TAAPSogeking

6
@JohnFeminella Bir bash senaryosunda yazarken, tek =değil iki değil.
user13107

72
kullanamayacağınızı belirtmeye değer olabilir [ $x -eq "valid" ]. -eqdizeler için değil tamsayılar için karşılaştırma operatörüdür.
craq

2
@Alex, Hangi durumlarda (eğer varsa) ["x$yes" == "xyes"], hem değişkene hem de dize değişmezine bir önek ekleyen deseni kullanmam gerekir x? Bu eski zamanların bir kalıntısı mı yoksa bazı durumlarda gerçekten gerekli mi?
lanoxx

142

Veya başka bir maddeye ihtiyacınız yoksa:

[ "$x" == "valid" ] && echo "x has the value 'valid'"

71
Ve başka bir maddeye ihtiyacınız varsa ve çılgın bir tek astar yapmak istiyorsanız: ["$ x" == "geçerli"] && echo "geçerli" || echo "geçersiz"
Matt White

11
@MattWhite: Bu echobaşarısız olabileceği gibi genellikle kötü bir fikirdir .
gniourf_gniourf

1
bile görünebilir tho markcha && MattWhite gelen güzel ve zarif yollar var
Deko

3
@gniourf_gniourf, sorun değil, kullanın [ "$X" == "valid" ] || ( echo invalid && false ) && echo "valid" .
12431234123412341234123

4
12431234123412341234123 @ { echo invalid && false; }daha etkilidir ( echo invalid && false )bunu gereksiz bir alt kabuğa için ödeme önler olarak.
Charles Duffy

84
a="abc"
b="def"

# Equality Comparison
if [ "$a" == "$b" ]; then
    echo "Strings match"
else
    echo "Strings don't match"
fi

# Lexicographic (greater than, less than) comparison.
if [ "$a" \< "$b" ]; then
    echo "$a is lexicographically smaller then $b"
elif [ "$a" \> "$b" ]; then
    echo "$b is lexicographically smaller than $a"
else
    echo "Strings are equal"
fi

Notlar:

  1. Arasındaki boşluklar ifve [ve ]önemlidir
  2. >ve <yeniden yönlendirme işleçleri bu nedenle dizelerden \>ve \<sırasıyla dizelerden kaçarlar .

6
Alfabetik sıra karşılaştırması için teşekkürler
shadi

Benim sorunum $aaslında " "dize değişmez değerinin bir parçası olarak çevreleyen vardı , bu nedenle $bdeğerleri karşılaştırmak için kaçış karakteri kullanmak zorunda kaldı . bash -x ./script.shÇalıştırdıktan sonra bunu bulabildim , -x bayrağı her yürütmenin değerini görmenizi sağlar ve hata ayıklamaya yardımcı olur.
ShahNewazKhan

Alfabetik sıra karşılaştırmasının POSIX standardında olmadığını unutmayın, bu nedenle GNU olmayan platformlarda / bash olmayan mermilerde çalışacağı garanti edilmez. Yalnızca pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html adresindeki işlemlerin taşınabilir olması garanti edilir.
Charles Duffy

62

Dizeleri joker karakterlerle karşılaştırmak için

if [[ "$stringA" == *$stringB* ]]; then
  # Do something here
else
  # Do Something here
fi

12
Joker karakterlerin sadece sağ tarafta kullanılabilmesi önemlidir! Ayrıca "joker karakterlerin eksikliğini de not edin . (btw: Joker karakterler için +1!)
Scz

6
Genişleme $stringB gerekir verilemeyecek (ve bu arada, sol taraftaki teklif edilecek gerekmez): if [[ $stringA = *"$stringB"* ]]; then.
gniourf_gniourf

ben dosyayolunda dosya adı için aynı joker mantığı kullanmaya çalışıyorum. Ama benim için çalışmıyor. burada sağlanan tüm farklı joker dizeleri denedim. ama her zaman başka bir davaya gider. Benim durumumda stringA bir dosya yoludur / tmp / dosya ve stringB "dosya" dır.
yağmur

35

Yorumlardan birini bir noktada katılmıyorum:

[ "$x" == "valid" ] && echo "valid" || echo "invalid"

Hayır, bu çılgın bir oneliner değil

Sadece biri gibi görünmüyor, hmm, deneyimsiz ...

Bir şekilde ortak kalıpları dil olarak kullanır;

Ve dili öğrendikten sonra.

Aslında okumak güzel

Özel bir kısmı olan basit bir mantıksal ifadedir: mantık operatörlerinin tembel değerlendirmesi.

[ "$x" == "valid" ] && echo "valid" || echo "invalid"

Her bölüm mantıklı bir ifadedir; birincisi doğru veya yanlış olabilir, diğer ikisi her zaman doğrudur.

(
[ "$x" == "valid" ] 
&&
echo "valid"
)
||
echo "invalid"

Şimdi, değerlendirildiğinde, ilk kontrol edilir. Yanlışsa, mantığın ikinci işlenmesinden ve && sonradan ilgili değildir. Birincisi doğru değil, bu yüzden ilk ve ikincisi doğru olamaz.
Şimdi, bu durumda mantığın ilk tarafı ya da || yanlış, ama diğer taraf - üçüncü kısım - doğruysa doğru olabilir.

Böylece üçüncü bölüm değerlendirilecektir - esas olarak mesajı bir yan etki olarak yazmak. (Burada kullanmadığımız sonuç 0doğrudur)

Diğer vakalar benzer, ama daha basit - ve - söz veriyorum! kolay okunabilir!
(Bende yok, ama bence gri sakallı UNIX emektarı olmak çok yardımcı oluyor.)


17
... && ... || ...O anlam eşdeğer değil gibi genellikle (Bütün bu zaman boyunca üzgün ihtiyar adam Unix gazisi, sen oldum yanlış) üzerine kaşlarını edilir if ... then ... else .... Endişelenme, bu yaygın bir tuzak .
gniourf_gniourf

6
@gniourf_gniourf OP yanlış değil - ne de önerdiğiniz gibi cahil değiller. ... && ... || ...son derece geçerli bir model ve ortak bir bash deyimidir. Kullanımı, ön bilgileri (izleyicide yeni başlayanlar varsa akılda tutmak iyi olabilir) reçete eder, ancak OP, açık rögar kapaklarından nasıl kaçınılacağını bildiklerini kanıtlamak için saçlara sahiptir.
ebpa

3
@ebpa && ifadesini izleyen deyim yanlış değerini döndürürse, yürütme aşağıdaki ifadeye devam eder || ? Eğer öyleyse bu yanlıştır ve belki de gniourf'un önerdiği şeydir
TSG

4
Eko'nun sadece bir örnek olduğunu düşündüm. && ifadesini izleyen ifade yine de sıfırdan farklı bir değer döndürebilir
TSG

2
@gniourf_gniourf +1 Bash Pitfalls! Çok kullanışlı!
Jaguar

21

ayrıca kullanım senaryosu / esac kullanabilirsiniz

case "$string" in
 "$pattern" ) echo "found";;
esac

Bu eşdeğerlik mi yoksa içerir mi?
ytpillai

@ytpillai, denkliktir. |Önce, ile ayrılmış kalıplara sahip olabileceğinizi unutmayın ). inİfadesi eşdeğerdir theniçinde iftablolar. Python'dan geliyorsanız, her listenin ne yapacağına dair kendi beyanına sahip olduğu bir desen listesi üzerinde çalıştığını iddia edebilirsiniz. Gibi değil substring in string, aksine for item in list. *Bir elsekoşul istiyorsanız, son ifadeniz olarak a kullanın . İlk karşılaşmada geri döner.
mazunki

18

Aşağıdaki komut dosyası "testonthis" adlı dosyayı satır satır okur ve her satırı basit bir dize, özel karakterli bir dize ve normal bir ifade ile karşılaştırır. Eşleşmezse, komut satırı satırı yazdırır, aksi takdirde yazdırmaz.

Bash'teki alan çok önemli. Yani aşağıdakiler işe yarayacak:

[ "$LINE" != "table_name" ] 

Ancak aşağıdakiler olmaz:

["$LINE" != "table_name"] 

Bu yüzden lütfen şu şekilde kullanın:

cat testonthis | while read LINE
do
if [ "$LINE" != "table_name" ] && [ "$LINE" != "--------------------------------" ] && [[ "$LINE" =~ [^[:space:]] ]] && [[ "$LINE" != SQL* ]]; then
echo $LINE
fi
done

Bir dosyadan geçmek için bu yaklaşımı kullanın . Yani, diğer şeylerin yanı sıra UUoC'yi çıkarın.
fedorqui 'SO

Çünkü önemli değil bashama [aslında harici bir ikili (gibi bir which [şey verir gibi /usr/bin/[)
Patrick Bergner

11

Girişin yalnızca birkaç geçerli girdisi varsa regexp eşleşmelerini kullanırım. Örneğin, yalnızca "başlat" ve "durdur" geçerli eylemlerdir.

if [[ "${ACTION,,}" =~ ^(start|stop)$ ]]; then
  echo "valid action"
fi

Ben $ACTIONçift ​​virgül kullanarak değişken küçük harf unutmayın . Ayrıca, bunun çok yaşlı bash sürümlerinde çalışmadığını unutmayın.


9

Bash 4+ örnekleri. Not: tırnak işareti kullanmamak kelimeler boşluk vb. İçerdiğinde sorunlara neden olur. Her zaman Bash, IMO'da alıntı yapın.

Bash 4+ ile ilgili bazı örnekler:

Örnek 1, dizede 'evet' olup olmadığını kontrol edin (büyük / küçük harf duyarsız):

    if [[ "${str,,}" == *"yes"* ]] ;then

Örnek 2, dizede 'evet' olup olmadığını kontrol edin (büyük / küçük harf duyarsız):

    if [[ "$(echo "$str" | tr '[:upper:]' '[:lower:]')" == *"yes"* ]] ;then

Örnek 3, dizede 'evet' olup olmadığını kontrol edin (büyük / küçük harfe duyarlı):

     if [[ "${str}" == *"yes"* ]] ;then

Örnek 4, dizede 'evet' olup olmadığını kontrol edin (büyük / küçük harfe duyarlı):

     if [[ "${str}" =~ "yes" ]] ;then

Örnek 5, tam eşleme (büyük / küçük harfe duyarlı):

     if [[ "${str}" == "yes" ]] ;then

Örnek 6, tam eşleme (büyük / küçük harf duyarlı):

     if [[ "${str,,}" == "yes" ]] ;then

Örnek 7, tam eşleme:

     if [ "$a" = "$b" ] ;then

Zevk almak.


benim için (mac GNU bash sürüm 4.4.12 (1) -çalışma x86_64-apple-darwin17.0.0), kullanmam gerekiyor if [ "$a"="$b" ]veya çalışmıyor ... eşittir etrafında boşluklar olamaz
spektrum

1

Bash ve Dash (sh) ile uyumlu şekilde yaptım :

testOutput="my test"
pattern="my"

case $testOutput in (*"$pattern"*)
    echo "if there is a match"
    exit 1
    ;;
(*)
   ! echo there is no coincidence!
;;esac

öncekinin kullanılmaması ile kullanılmaması arasındaki fark (nedir?
mazunki
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.