Bir dizgenin bash'ta baska bir alt dize olup olmadığı nasıl belirlenir?


49

Bir dize başka bir dize bir kısmı içinde olup olmadığını görmek istiyorum .
Örneğin:

'ab' in 'abc' -> true
'ab' in 'bcd' -> false

Bunu bir bash betiğine bağlı olarak nasıl yapabilirim?

Yanıtlar:


27

Sen formu kullanabilirsiniz büyük dizesi içerir ve sizin bulmaya çalışıyoruz alt dize geçerli:${VAR/subs}VARsubs

my_string=abc
substring=ab
if [ "${my_string/$substring}" = "$my_string" ] ; then
  echo "${substring} is not in ${my_string}"
else
  echo "${substring} was found in ${my_string}"
fi

Bu işe yarıyor, çünkü çıkartılan dizenin ilk oluşumu ${VAR/subs}eşittir, $VARancak subsözellikle değiştirilmeyecek $VARkelimeyi içermiyorsa subs.


echoİfadelerin sırasını değiştirmeniz gerektiğini düşünüyorum . Çünkü benab is not in abc
Lucio,

Haklısın! : P
edwin

Mmm .. Hayır, senaryo yanlış. Bunun gibi ben olsun ab was found in abc, ama kullanırsanız substring=zalıyorumz was found in abc
Lucio

1
Şimdi anladım ab is not in abc. Ama z was found in abc. Bu komik: D
Lucio

1
Yaa! Ekolar bunun başında haklıydı! XD
edwin

47

[[ "bcd" =~ "ab" ]]
[[ "abc" =~ "ab" ]]

parantezler test içindir ve çift parantezler olduğundan bazı ekstra testler yapabilir =~.

Böylece bu formu bir şey gibi kullanabilirsiniz

var1="ab"
var2="bcd"
if [[ "$var2" =~ "$var1" ]]; then
    echo "pass"
else
    echo "fail"
fi

Düzenleme: "= ~" düzeltildi, ters çevrildi.


1
failBu parametrelerle alıyorum :var2="abcd"
Lucio

3
@ Lucio Doğru [[ $string =~ $substring ]]. Cevabı güncelledim.
Eric Carvalho

12

Bash dosya adı kalıplarını kullanma (aka "glob" kalıpları)

substr=ab
[[ abc == *"$substr"* ]] && echo yes || echo no    # yes
[[ bcd == *"$substr"* ]] && echo yes || echo no    # no

eğer [["$ JAVA_OPTS"! = "-XX: + UseCompressedOops" ]]; daha sonra JAVA_OPTS = "$ JAVA_OPTS -XX: + UseCompressedOops"; fi
Mike Slinn

10

Aşağıdaki iki yaklaşım sadece bash değil, POSIX uyumlu herhangi bir ortamda da çalışacaktır:

substr=ab
for s in abc bcd; do
    if case ${s} in *"${substr}"*) true;; *) false;; esac; then
        printf %s\\n "'${s}' contains '${substr}'"
    else
        printf %s\\n "'${s}' does not contain '${substr}'"
    fi
done
substr=ab
for s in abc bcd; do
    if printf %s\\n "${s}" | grep -qF "${substr}"; then
        printf %s\\n "'${s}' contains '${substr}'"
    else
        printf %s\\n "'${s}' does not contain '${substr}'"
    fi
done

Yukarıdaki çıktıların her ikisi de:

'abc' contains 'ab'
'bcd' does not contain 'ab'

İlki, ayrı bir grepsürecin doğmaması avantajına sahiptir .

Ben kullandığını unutmayın printf %s\\n "${foo}"yerine echo "${foo}"NEDENİYLE echobozmak olabilir ${foo}o ters eğik çizgi içeriyorsa.


İlk versiyon xrandrdeğişkende saklanan monitör adları listesinde monitör adının alt dizini bulmak için mükemmel çalışır . +1 ve 1K rep club'a hoş geldiniz :)
WinEunuuchs2Unix

6

kabuk örneği

Bu, en taşınabilir çözümdür, eski Bourne mermileri ve Korn mermisi üzerinde bile çalışacaktır.

#!/bin/bash
case "abcd" in
    *$1*) echo "It's a substring" ;;
    *) echo "Not a substring" ;;
esac

Örnek çalışma:

$ ./case_substr.sh "ab"                                                                                           
It's a substring
$ ./case_substr.sh "whatever"                                                                                     
Not a substring

Özellikle kullanmak zorunda unutmayın echokullanabileceğiniz exit 1ve exit 0başarılı veya başarısız belirtmek için.

Bizim de yapabileceğimiz şey, belirli dönüş değerleriyle (eşleşme 0, eşleşme 1 değil) belirli bir dönüş değerine sahip (gerekirse büyük komut dosyalarında kullanılabilir) bir işlev oluşturmaktır:

$ ./substring_function.sh                                  
ab is substring

$ cat substring_function.sh                                
#!/bin/sh

is_substring(){
    case "$2" in
        *$1*) return 0;;
        *) return 1;;
    esac
}

main(){
   if is_substring "ab" "abcdefg"
   then
       echo "ab is substring"
   fi
}

main $@

grep

$ grep -q 'ab' <<< "abcd" && echo "it's a substring" || echo "not a substring"                                    
it's a substring

Bu özel yaklaşım, içindeki if-else ifadelerinde kullanışlıdır bash. Ayrıca çoğunlukla taşınabilir

AWK

$ awk '$0~/ab/{print "it is a substring"}' <<< "abcd"                                                             
it is a substring

piton

$ python -c 'import sys;sys.stdout.write("it is a substring") if "ab" in sys.stdin.read() else exit(1)' <<< "abcd"
it is a substring

Yakut

$ ruby -e ' puts "is substring" if  ARGV[1].include? ARGV[0]'  "ab" "abcdef"                                             
is substring

Herkesin üstünde ve ötesinde gitmek için +1. Burada farkettim ve diğer yığın değişim sitelerinde hiçbir cevap, alt dizenin dize içindeki ofsetini döndürmez. Bu geceki görevimiz :)
WinEunuuchs2Unix

@ WinEunuuchs2Unix Bunu bash olarak mı yapacaksın?
Sergiy Kolodyazhnyy

Evet ve Hayır. Python'un tüm gmail.com mesajlarının meta verilerini ve bash'ı ayrıştırdığı ve detaylandırılmış bir GUI listesi sunduğu Frankenstein projesi yapıyorum. Cevabı burada buldum: stackoverflow.com/questions/5031764/…
WinEunuuchs2Unix

@ WinEunuuchs2Unix Tamam. Kulağa ilginç geliyor. Şahsen Python'daki her şeyi ayrıştırmayı tercih ederdim. Metin işleme için yalnızca bash'ten çok daha fazla özelliği vardır.
Sergiy Kolodyazhnyy

İki senedir tercihlerini biliyorum ve onlara saygı duyuyorum. Ama ben sadece Python'u öğreniyorum ve onunla çalışmak için yad almak bana çok zor geliyor. Bash'ta zaten rahat ettiğim tüm dizi işlemlerinden bahsetmiyorum bile. Ama en azından, ilk python betiğimi google’ın gmail.com’ındaki her şeyi Linux düz dosyasına aktarmak için yazdım. :)
WinEunuuchs2Unix

5

Dikkat et [[ve ":

[[ $a == z* ]]   # True if $a starts with an "z" (pattern matching).
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).

[ $a == z* ]     # File globbing and word splitting take place.
[ "$a" == "z*" ] # True if $a is equal to z* (literal matching).

Glenn_jackman'ın dediği gibi, ancak tüm ikinci terimi çift tırnak işaretleri arasına alırsanız, testi gerçek anlamıyla eşleştireceğinize dikkat edin.

Kaynak: http://tldp.org/LDP/abs/html/comparison-ops.html


4

Edwin'in cevabına benzer şekilde, ancak posix & ksh için geliştirilmiş taşınabilirlik ve Richard'ınkinden daha az gürültülü bir dokunuşla:

substring=ab

string=abc
if [ "$string" != "${string%$substring*}" ]; then
    echo "$substring IS in $string"
else
    echo "$substring is NOT in $string"
fi

string=bcd
if [ "$string" != "${string%$substring*}" ]; then
    echo "$string contains $substring"
else
    echo "$string does NOT contain $substring"
fi

Çıktı:

abc contains ab
bcd does NOT contain ab
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.