Bir dizenin Bash'de bir alt dize içerip içermediğini kontrol etme


2568

Bash bir dize var:

string="My string"

Başka bir dize içerip içermediğini nasıl test edebilirim?

if [ $string ?? 'foo' ]; then
  echo "It's there!"
fi

??Bilinmeyen operatörüm nerede . Yankı ve grepmı kullanırım ?

if echo "$string" | grep 'foo'; then
  echo "It's there!"
fi

Biraz sakar görünüyor.


4
Merhaba, eğer boş dizeler yanlışsa, neden sakar olduğunu düşünüyorsun? Önerilen çözümlere rağmen benim için çalışan tek yol buydu.
ericson.cepeda

1
exprKomutu burada kullanabilirsiniz
cli__

4
İşte posix kabukları için bir tane: stackoverflow.com/questions/2829613/…
sehe

Yanıtlar:


3652

Çift parantez kullanıyorsanız Marcus yanıtını (* joker karakterlerini) bir vaka ifadesinin dışında da kullanabilirsiniz:

string='My long string'
if [[ $string == *"My long"* ]]; then
  echo "It's there!"
fi

İğne dizesindeki boşlukların çift tırnak arasına *alınması ve joker karakterlerin dışarıda olması gerektiğini unutmayın. Ayrıca ==regex operatörünün değil, basit bir karşılaştırma operatörünün kullanıldığını (yani ) unutmayın =~.


127
Ayrıca, testte! = 'Ye geçerek karşılaştırmayı tersine çevirebileceğinizi de unutmayın. Cevap için teşekkürler!
Quinn Taylor

63
@Jonik: Mesele eksik ya da sahip olabilir #!/bin/sh. #!/bin/bashBunun yerine deneyin .
sonraki duyuruya kadar duraklatıldı.

10
Köşeli ayraçlar ve içindekiler arasında boşluk bırakın.
Paul Price

17
[[]] İçindeki değişkenleri alıntılamanız gerekmez. Bu da işe yarayacak: [[$ string == $ needle ]] && echo bulundu
Orwellophile

12
@Orwellophile Dikkatli ol! Yalnızca ilk bağımsız değişkenindeki çift tırnak işaretlerini atlayabilirsiniz [[. Bakınız ideone.com/ZSy1gZ
nyuszika7h

611

Normal ifade yaklaşımını tercih ediyorsanız:

string='My string';

if [[ $string =~ "My" ]]
then
   echo "It's there!"
fi

2
Bir bash komut dosyasında bir egrep regex değiştirmek zorunda kaldı, bu mükemmel çalıştı!
blast_hardcheese

114
=~Operatör zaten maç için tüm dizeyi arar; .*işte yabancı bulunmaktadır. Ayrıca, teklifler genellikle ters eğik çizgilere tercih edilir:[[ $string =~ "My s" ]]
bukzor

16
@bukzor Alıntılar Bash 3.2+ itibariyle burada çalışmayı durdurdu: tiswww.case.edu/php/chet/bash/FAQE14) . Bir değişkene (tırnak işaretleri kullanarak) atamak ve karşılaştırmak muhtemelen en iyisidir. re="My s"; if [[ $string =~ $re ]]
Şunun

36
Bir dize İÇERMEDİĞİNİ test edin : if [[ ! "abc" =~ "d" ]]true.
KrisWebDev

1
Testin gerçekleşme sırasının önemli olduğuna dikkat edin. Aşağıdaki kod satırının çıktısı 2 olacak.number=2; if [[ "1, 2, 4, 5" = *${number}* ]]; then echo forward $number; fi; if [[ *${number}* = "1, 2, 4, 5" ]]; then echo backwards $number; fi;
Douwe van der Leest

356

Bir if ifadesi kullanma konusunda emin değilim, ancak bir case ifadesiyle benzer bir etki elde edebilirsiniz:

case "$string" in 
  *foo*)
    # Do stuff
    ;;
esac

76
Bu muhtemelen en iyi çözümdür çünkü kabukları posixlemek için taşınabilir. (hayır bashisms aka)
technosaurus

25
@technosaurus Ben sadece bash etiketi olan bir soruda "bashizm" eleştirmek oldukça garip buluyorum :)
PP

39
@ PP Bu daha sınırlı bir çözüm yerine daha evrensel bir çözümün tercihi kadar bir eleştiri değildir. Yıllar sonra, (benim gibi) insanların bu cevabı aramak için duracaklarını ve orijinal sorudan daha geniş bir kapsamda faydalı olanları bulmaktan memnuniyet duyabileceklerini lütfen unutmayın. Açık Kaynak dünyasında söyledikleri gibi: "seçim iyidir!"
Carl Smotricz

2
@technosaurus, FWIW [[ $string == *foo* ]]ayrıca POSIX uyumlu bazı sh sürümlerinde (örneğin /usr/xpg4/bin/shSolaris 10'da) ve
ksh'da

3
Busybox kül yıldız işaretleri işlemez [[ kutusu ... kasa anahtarı işe yaradı!
Ray Foss

232

stringContain varyantlar (uyumlu veya büyük / küçük harf bağımsız)

Bu Stack Overflow cevapları çoğunlukla Bash hakkında söylediği gibi, bu yazının en altında bir vakadan bağımsız Bash işlevi yayınladım ...

Her neyse, işte benim

Uyumlu cevap

Bash'e özgü özellikleri kullanan birçok yanıt olduğundan, BusyBox gibi daha kötü özellikli kabuklarda çalışmanın bir yolu var :

[ -z "${string##*$reqsubstr*}" ]

Uygulamada, bu aşağıdakileri verebilir:

string='echo "My string"'
for reqsubstr in 'o "M' 'alt' 'str';do
  if [ -z "${string##*$reqsubstr*}" ] ;then
      echo "String '$string' contain substring: '$reqsubstr'."
    else
      echo "String '$string' don't contain substring: '$reqsubstr'."
    fi
  done

Bu Bash, Dash , KornShell ( ksh) ve ash (BusyBox) ve sonuç her zaman:

String 'echo "My string"' contain substring: 'o "M'.
String 'echo "My string"' don't contain substring: 'alt'.
String 'echo "My string"' contain substring: 'str'.

Bir işleve

@EeroAaltonen tarafından sorulduğu gibi, aynı demonun aynı kabuklar altında test edilmiş bir versiyonu:

myfunc() {
    reqsubstr="$1"
    shift
    string="$@"
    if [ -z "${string##*$reqsubstr*}" ] ;then
        echo "String '$string' contain substring: '$reqsubstr'.";
      else
        echo "String '$string' don't contain substring: '$reqsubstr'."
    fi
}

Sonra:

$ myfunc 'o "M' 'echo "My String"'
String 'echo "My String"' contain substring 'o "M'.

$ myfunc 'alt' 'echo "My String"'
String 'echo "My String"' don't contain substring 'alt'.

Farkına varmak: Tırnaklardan ve / veya çift tırnaklardan kaçmak veya çift tırnak içine almak zorundasınız:

$ myfunc 'o "M' echo "My String"
String 'echo My String' don't contain substring: 'o "M'.

$ myfunc 'o "M' echo \"My String\"
String 'echo "My String"' contain substring: 'o "M'.

Basit fonksiyon

Bu BusyBox, Dash ve elbette Bash altında test edildi:

stringContain() { [ -z "${2##*$1*}" ]; }

Öyleyse şimdi:

$ if stringContain 'o "M3' 'echo "My String"';then echo yes;else echo no;fi
no
$ if stringContain 'o "M' 'echo "My String"';then echo yes;else echo no;fi
yes

... Veya gönderilen dize @Sjlver tarafından belirtildiği gibi boş olsaydı, işlev şöyle olur:

stringContain() { [ -z "${2##*$1*}" ] && [ -z "$1" -o -n "$2" ]; }

ya da Adrian Günter'in yorumunda önerildiği gibi , -oanahtarlardan kaçınarak :

stringContain() { [ -z "${2##*$1*}" ] && { [ -z "$1" ] || [ -n "$2" ];};}

Son (basit) fonksiyon:

Ve potansiyel olarak daha hızlı hale getirmek için testleri tersine çevirmek:

stringContain() { [ -z "$1" ] || { [ -z "${2##*$1*}" ] && [ -n "$2" ];};}

Boş dizelerle:

$ if stringContain '' ''; then echo yes; else echo no; fi
yes
$ if stringContain 'o "M' ''; then echo yes; else echo no; fi
no

Büyük / küçük harf bağımsız (yalnızca Bash!)

Dizeleri büyük / küçük harf olmadan test etmek için, her dizeyi küçük harfe dönüştürmeniz yeterlidir:

stringContain() {
    local _lc=${2,,}
    [ -z "$1" ] || { [ -z "${_lc##*${1,,}*}" ] && [ -n "$2" ] ;} ;}

Kontrol:

stringContain 'o "M3' 'echo "my string"' && echo yes || echo no
no
stringContain 'o "My' 'echo "my string"' && echo yes || echo no
yes
if stringContain '' ''; then echo yes; else echo no; fi
yes
if stringContain 'o "M' ''; then echo yes; else echo no; fi
no

1
Eğer bunu bir fonksiyona sokmanın bir yolunu bulabilirseniz, bu daha da iyi olurdu.
Eero Aaltonen

2
@EeroAaltonen (yeni eklenen) işlevimi nasıl bulabilirsin?
F. Hauri

2
Biliyorum! bulmak. -adı "*" | xargs grep "myfunc" 2> / dev / null
eggmatters

6
Bu harika çünkü çok uyumlu. Ancak bir hata: Samanlık dizesi boşsa çalışmaz. Doğru sürüm string_contains() { [ -z "${2##*$1*}" ] && [ -n "$2" -o -z "$1" ]; } Son bir düşünce olacaktır: boş dize boş dize içeriyor mu? Yukarıdaki şey evet sürümü (çünkü -o -z "$1"parçası).
Sjlver

3
+1. Çok iyi! Benim için sipariş dizesini değiştirdimContain () {[-z "$ {1 ## * $ 2 *}"] && [-z "$ 2" -o -n "$ 1"]; }; Msgstr "Nerede ara" "Neyi bul". Meşgul kutusunda çalışın. Kabul edilen yukarıdaki yanıt meşgul kutusunda çalışmıyor.
user3439968

149

Kabuk betiklemenin bir dilden daha az ve daha çok komutlar topluluğu olduğunu hatırlamanız gerekir. İçgüdüsel olarak, bu "dil" ifin a [veya a ile takip etmenizi gerektirdiğini düşünüyorsunuz [[. Her ikisi de sadece başarı veya başarısızlık gösteren bir çıkış durumu döndüren komutlardır (diğer tüm komutlarda olduğu gibi). Bu nedenle grep,[ komuta.

Sadece yap:

if grep -q foo <<<"$string"; then
    echo "It's there"
fi

Şimdi ifonu izleyen komutun çıkış durumunu (yarı kolon ile tamamlanmış) test etmeyi düşündüğünüze göre , neden test ettiğiniz dizenin kaynağını yeniden düşünmüyorsunuz?

## Instead of this
filetype="$(file -b "$1")"
if grep -q "tar archive" <<<"$filetype"; then
#...

## Simply do this
if file -b "$1" | grep -q "tar archive"; then
#...

Bu -qseçenek, yalnızca dönüş kodunu istediğimizden, grep'in hiçbir şey çıkarmamasını sağlar. <<<Kabuğun bir sonraki sözcüğü genişletmesini ve komutun girdisi olarak kullanmasını sağlar, <<burada belgenin tek satırlık bir sürümü (bunun standart mı yoksa Bashizm mi olduğundan emin değilim).


7
burada dizeler (3.6.7) olarak adlandırılırlar Ben bashizm olduğuna inanıyorum
alex.pilon

10
bir de Süreç if grep -q foo <(echo somefoothing); then
Değişimi

Not echoEğer bir değişken geçirerek eğer unportable olduğunu, kullanmak printf '%s' "$stringyerine.
nyuszika7h

5
Bunun maliyeti çok pahalı: grep -q foo <<<"$mystring"implie 1 çatal yapmak ve bashizm ve echo $mystring | grep -q foo2 çatal implie (bir boru için ve ikinci çalıştırmak için /path/to/grep)
F. Hauri

1
Bağımsız echodeğişken dizesi ters eğik çizgi dizileri içeriyorsa, bayrakları olmayan @BrunoBronosky yine de beklenmedik taşınabilirlik sorunları yaşayabilir. echo "nope\c"bazı platformlarda bazılarında olduğu gibi çalışması bekleniyor echo -e "nope". printf '%s' "nope"vsprintf '%s\n' 'nope\c'
tripleee

92

Kabul edilen cevap en iyisidir, ancak bunu yapmanın birden fazla yolu olduğundan, işte başka bir çözüm:

if [ "$string" != "${string/foo/}" ]; then
    echo "It's there!"
fi

${var/search/replace}olduğu $varilk örneği ile searchyerine replaceo bulunursa, (o değişmez $var). fooHiçbir şeyle değiştirmeyi denerseniz ve dize değiştiyse, açıkçası foobulundu.


5
ephemient'in yukarıdaki çözümü:> `if [" $ string "! =" $ {string / foo /} "]; sonra yankı "Orada!" fi`, BusyBox'ın kabuk külü kullanılırken kullanışlıdır . Bazı bash'ın düzenli ifadeleri uygulanmadığından, kabul edilen çözüm BusyBox ile çalışmaz.
TPoschel

1
fark eşitsizliği. Oldukça garip bir düşünce! I love it
nitinr708

1

Aynı çözümü kendim yazdım (çünkü tercümanım en iyi cevapları almayacaktı) sonra daha iyi bir çözüm aramaya gitti, ama buldum!
BuvinJ

56

Yani soruya birçok yararlı çözüm var - ama hangisi en hızlı / en az kaynağı kullanıyor?

Bu çerçeveyi kullanarak tekrarlanan testler:

/usr/bin/time bash -c 'a=two;b=onetwothree; x=100000; while [ $x -gt 0 ]; do TEST ; x=$(($x-1)); done'

Her seferinde TEST'in değiştirilmesi:

[[ $b =~ $a ]]           2.92 user 0.06 system 0:02.99 elapsed 99% CPU

[ "${b/$a//}" = "$b" ]   3.16 user 0.07 system 0:03.25 elapsed 99% CPU

[[ $b == *$a* ]]         1.85 user 0.04 system 0:01.90 elapsed 99% CPU

case $b in *$a):;;esac   1.80 user 0.02 system 0:01.83 elapsed 99% CPU

doContain $a $b          4.27 user 0.11 system 0:04.41 elapsed 99%CPU

(doContain F. Houri'nin cevabındaydı)

Ve kıkırdamalar için:

echo $b|grep -q $a       12.68 user 30.86 system 3:42.40 elapsed 19% CPU !ouch!

Böylece basit ikame seçeneği, genişletilmiş bir testte veya bir vakada tahmin edilebilir şekilde kazanır. Kasa taşınabilir.

100000 açığa çıkan boruları tahmin etmek acı verici! Harici yardımcı programların ihtiyaç duyulmadan kullanılmasına ilişkin eski kural geçerlidir.


4
Düzgün kriter. Beni kullanmaya ikna ettim [[ $b == *$a* ]].
Mad Physicist

2
Bunu doğru okuyorsam, casetoplamda en az zaman harcayarak kazanır. $b in *$aYine de bir yıldız işareti eksik . Ben biraz daha hızlı sonuç almak [[ $b == *$a* ]]için daha casehata düzeltilmiş ile, ancak tabii ki, çok başka faktörlere bağlı olabilir.
tripleee

1
ideone.com/5roEVt bazı ek hatalar düzeltildi ve farklı bir senaryo için testler yaptı (burada dize aslında daha uzun dizede mevcut değil). Sonuçlar büyük ölçüde benzerdir;[[ $b == *$a* ]]hızlı ve caseneredeyse hızlı (ve hoş bir POSIX uyumlu).
tripleee

28

Bu ayrıca işe yarar:

if printf -- '%s' "$haystack" | egrep -q -- "$needle"
then
  printf "Found needle in haystack"
fi

Ve negatif test:

if ! printf -- '%s' "$haystack" | egrep -q -- "$needle"
then
  echo "Did not find needle in haystack"
fi

Bu tarzın biraz daha klasik olduğunu düşünüyorum - Bash kabuğunun özelliklerine daha az bağımlı.

--Argüman gibi seçenekler, benzer girdi dizeleri karşı korunan kullanılan saf POSIX paranoya vardır --abcya -a.

Not: Sıkı bir döngüde, bu kod dahili Bash kabuğu özelliklerini kullanmaktan çok daha yavaş olacaktır , çünkü borularla bir (veya iki) ayrı işlem oluşturulacak ve bağlanacaktır.


5
... ama OP hangi bash versiyonunu söylemiyor ; örneğin, eski bash (sıklıkla solaris gibi) bu yeni bash özelliklerini içermeyebilir. (Ben bash 2.0 w / solaris bu kesin sorun (bash desen eşleştirme uygulanmadı) karşılaştım)
michael

2
echotaşınabilir değil, printf '%s' "$haystackbunun yerine kullanmanız gerekir .
nyuszika7h

2
Hayır, sadece echobir ile başlamamış kaçışsız gerçek metin dışında bir şey için tamamen kaçının -. Sizin için işe yarayabilir, ancak taşınabilir değildir. Bash bile seçeneğin ayarlanıp ayarlanmadığına echobağlı olarak farklı davranacaktır xpg_echo. Not: Önceki yorumumda çift alıntıyı kapatmayı unuttum.
nyuszika7h

1
@kevinarpe Emin değilim --, POSIX spesifikasyonundaprintf listelenmiyor , ancak bir karakter içeriyorsa printf '%s' "$anything"sorunları önlemek için yine de kullanmalısınız . $anything%
nyuszika7h

1
@kevinarpe Buna dayanarak, muhtemelen öyle.
nyuszika7h

21

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

İşte bazı örnekler Bash 4+:

Ö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

Örnek 8, joker karakter eşleşmesi .ext (büyük / küçük harf duyarlı):

     if echo "$a" | egrep -iq "\.(mp[3-4]|txt|css|jpg|png)" ; then

Zevk almak.


17

Buna ne dersin:

text="   <tag>bmnmn</tag>  "
if [[ "$text" =~ "<tag>" ]]; then
   echo "matched"
else
   echo "not matched"
fi

2
= ~ normal ifade eşleşmesi içindir, dolayısıyla OP'nin amacı için çok güçlüdür.

16

As Paul söz onun performansı karşılaştırıldığında:

if echo "abcdefg" | grep -q "bcdef"; then
    echo "String contains is true."
else
    echo "String contains is not true."
fi

Bu, Marcus tarafından verilen cevaptaki 'case "$ string" gibi POSIX uyumludur , ancak vaka bildirimi yanıtından okumak biraz daha kolaydır. Bunun bir vaka ifadesi kullanmaktan çok daha yavaş olacağını da unutmayın. Paul'un işaret ettiği gibi, onu bir döngü içinde kullanmayın.



9
[[ $string == *foo* ]] && echo "It's there" || echo "Couldn't find"

echo "Couldn't findSonunda ifade bu eşleşen komutlar için 0 çıkış durumları döndürmek için güzel bir hile olduğunu ekleyeceğiz .
nicodjimenez

@nicodjimenez artık bu çözümle çıkış durumunu hedefleyemezsiniz. Çıkış durumu, durum mesajları tarafından yutulur ...
Jahid

1
Demek istediğim tam olarak budur ... Eğer || echo "Couldn't find"yoksa, eşleşme yoksa bir hata çıkış durumu döndürürsünüz, örneğin tüm komutların geri dönmesini istediğiniz yerde bir CI boru hattı çalıştırıyorsanız istemeyebilirsiniz. hatasız çıkış durumları
nicodjimenez

9

Biri:

[ $(expr $mystring : ".*${search}.*") -ne 0 ] && echo 'yes' ||  echo 'no'

2
exprnasıl yapacağınızı anladıktan sonra, genellikle yapmanız gereken her şeyi yapabilen İsviçre-ordu-bıçak yardımcı programlarından biridir, ancak bir kez uygulandığında, ne yaptığını veya ne yaptığını asla hatırlayamazsınız, böylece bir daha asla dokunmayın ve umarım yaptığı şeyi yapmayı asla bırakmaz.
michael

@AloisMahdal Asla aşağı oy vermedim, neden aşağı oy verildiğini varsayıyorum. Dikkatli bir yorum. exprTaşınabilirlik bash (örneğin, eski sürümlerde tutarsız davranış), tr (her yerde tutarsız) veya sed (bazen çok yavaş) kullanımını önlediğinde nadiren kullanırım. Ama kişisel deneyimlerden, bu exprşeyleri yeniden okuduğumda , man sayfasına geri dönmem gerekiyor. Yani, sadece her kullanımın expryorumlanacağını yorumlayacağım ...
michael

1
Tüm sahip olduğunuz orijinal Bourne kabuğunun olduğu bir zaman vardı. Bu araçlar gibi bu yüzden, bazı yaygın gerekli özellikleri yoksun exprve testbunları gerçekleştirmek için uygulanmıştır. Bu gün ve yaşta, çoğu herhangi bir modern kabuğa yerleştirilmiş genellikle daha iyi araçlar vardır. Sanırım testhala orada asılı duruyor ama kimse kayıp gibi görünmüyor expr.
tripleee

6

Sed'i severim.

substr="foo"
nonsub="$(echo "$string" | sed "s/$substr//")"
hassub=0 ; [ "$string" != "$nonsub" ] && hassub=1

Düzenle, Mantık:

  • Dizeden alt dize örneğini kaldırmak için sed kullanın

  • Yeni dize eski dizeden farklıysa, alt dize vardır


2
Lütfen biraz açıklama ekleyin. Temel mantığı uygulamak sadece kodu vermekten daha önemlidir, çünkü OP ve diğer okuyucuların bunu ve benzer sorunları kendileri düzeltmelerine yardımcı olur
Zulan

5

grep -q bu amaç için yararlıdır.

Aynı kullanarak awk:

string="unix-bash 2389"
character="@"
printf '%s' "$string" | awk -vc="$character" '{ if (gsub(c, "")) { print "Found" } else { print "Not Found" } }'

Çıktı:

Bulunamadı

string="unix-bash 2389"
character="-"
printf '%s' "$string" | awk -vc="$character" '{ if (gsub(c, "")) { print "Found" } else { print "Not Found" } }'

Çıktı:

Bulundu

Orijinal kaynak: http://unstableme.blogspot.com/2008/06/bash-search-letter-in-string-awk.html


3
echotaşınabilir değil, printf '%s' "$string"bunun yerine kullanmanız gerekir . Cevabı düzenliyorum çünkü kullanıcı artık görünmüyor.
nyuszika7h

Ne şekilde echotaşınabilir değil, @ nyuszika7h?
starbeamrainbowlabs

5

Bu işlevselliğe oldukça sık ihtiyacım var, bu yüzden evimde bir kabuk işlevi kullanıyorum, bu .bashrcşekilde hatırlamam kolay bir adla ihtiyacım olduğu kadar sık ​​kullanmamı sağlıyor:

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

Test için eğer $string1(diyelim, abc ) bulunan $string2(mesela 123abcABC Sadece çalıştırmak gerekir) stringinstring "$string1" "$string2", örneğin ve dönüş değeri denetlemek

stringinstring "$str1" "$str2"  &&  echo YES  ||  echo NO

[["$ str" == $ substr ]] && echo YES || echo NO
elyase

Kesin xkesmek sadece çok eski kabuklar için gerekli eminim .
nyuszika7h

5

Benim .bash_profile dosyası ve ben grep nasıl kullandığını:

PATH ortam değişkeni iki bindizinimi içeriyorsa , onları eklemeyin,

# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

U=~/.local.bin:~/bin

if ! echo "$PATH" | grep -q "home"; then
    export PATH=$PATH:${U}
fi

1
Bu bir cevap mı?
codeforester

upvote. neden Bash'in çok daha güçlü olan grep'in mevcut olacağından daha fazla olduğu zaman bunu nasıl yaptığını öğrenmek için uğraşmayın. Ayrıca desen listesine göre eşleme tarafından biraz daha ileri uzatmak: grep -q -E 'pattern1|...|patternN'.
Mohamed Bana

4

Yanıtlanan sorunun uzantısı burada bir dizenin POSIX sh içinde başka bir dize olup olmadığını nasıl anlarsınız? :

Bu çözüm özel karakterlerle çalışır:

# contains(string, substring)
#
# Returns 0 if the specified string contains the specified substring,
# otherwise returns 1.
contains() {
    string="$1"
    substring="$2"

    if echo "$string" | $(type -p ggrep grep | head -1) -F -- "$substring" >/dev/null; then
        return 0    # $substring is in $string
    else
        return 1    # $substring is not in $string
    fi
}

contains "abcd" "e" || echo "abcd does not contain e"
contains "abcd" "ab" && echo "abcd contains ab"
contains "abcd" "bc" && echo "abcd contains bc"
contains "abcd" "cd" && echo "abcd contains cd"
contains "abcd" "abcd" && echo "abcd contains abcd"
contains "" "" && echo "empty string contains empty string"
contains "a" "" && echo "a contains empty string"
contains "" "a" || echo "empty string does not contain a"
contains "abcd efgh" "cd ef" && echo "abcd efgh contains cd ef"
contains "abcd efgh" " " && echo "abcd efgh contains a space"

contains "abcd [efg] hij" "[efg]" && echo "abcd [efg] hij contains [efg]"
contains "abcd [efg] hij" "[effg]" || echo "abcd [efg] hij does not contain [effg]"

contains "abcd *efg* hij" "*efg*" && echo "abcd *efg* hij contains *efg*"
contains "abcd *efg* hij" "d *efg* h" && echo "abcd *efg* hij contains d *efg* h"
contains "abcd *efg* hij" "*effg*" || echo "abcd *efg* hij does not contain *effg*"

Test contains "-n" "n"burada işe yaramıyor çünkü bir seçenek olarak echo -nyutacak -n! Bunun için popüler bir düzeltme kullanmaktır printf "%s\n" "$string".
joeytwiddle

mükemmel, çözülen dize boşluk içeren
dengApro

4

Yana POSIX / BusyBox soru doğru cevabı (IMHO) sağlamadan kapalıdır, burada bir yanıt göndeririz.

Mümkün olan en kısa cevap:

[ ${_string_##*$_substring_*} ] || echo Substring found!

veya

[ "${_string_##*$_substring_*}" ] || echo 'Substring found!'

Not çift karma olan zorunlu bazı kabuklu ( ash). Yukarıdaki [ stringvalue ], alt dize bulunmadığında değerlendirilecektir . Hiçbir hata döndürmez. Alt dize bulunduğunda sonuç boştur ve değerlendirir [ ]. Bu, dize tamamen değiştirildiği için hata kodu 1'i atar (nedeniyle* ) .

En kısa ve daha yaygın sözdizimi:

[ -z "${_string_##*$_substring_*}" ] && echo 'Substring found!'

veya

[ -n "${_string_##*$_substring_*}" ] || echo 'Substring found!'

Bir diğeri:

[ "${_string_##$_substring_}" != "$_string_" ] && echo 'Substring found!'

veya

[ "${_string_##$_substring_}" = "$_string_" ] || echo 'Substring found!'

Tek eşit işareti not edin !


3

Tam kelime eşleme:

string='My long string'
exactSearch='long'

if grep -E -q "\b${exactSearch}\b" <<<${string} >/dev/null 2>&1
  then
    echo "It's there"
  fi

3

Oobash'ı deneyin.

Bash 4 için OO tarzı bir dize kitaplığıdır. Bash ile yazılmıştır.

Birçok fonksiyonları mevcuttur: -base64Decode, -base64Encode, -capitalize, -center, -charAt, -concat, -contains, -count, -endsWith, -equals, -equalsIgnoreCase, -reverse, -hashCode, -indexOf, -isAlnum, -isAlpha, -isAscii, -isDigit, -isEmpty, -isHexDigit, -isLowerCase, -isSpace, -isPrintable, -isUpperCase, -isVisible, -lastIndexOf, -length, -matches, -replaceAll, -replaceFirst, -startsWith, -substring, -swapCase, -toLowerCase, -toString, -toUpperCase, -trim, ve -zfill.

Bak içeren örnek:

[Desktop]$ String a testXccc
[Desktop]$ a.contains tX
true
[Desktop]$ a.contains XtX
false

oobash Sourceforge.net adresinde mevcuttur .


2

Bu işlevi kullanıyorum (bir bağımlılık dahil değil açıktır). Aşağıda gösterilen testleri geçer. İşlev> 0 değerini döndürürse, dize bulundu. Bunun yerine kolayca 1 veya 0 döndürebilirsiniz.

function str_instr {
   # Return position of ```str``` within ```string```.
   # >>> str_instr "str" "string"
   # str: String to search for.
   # string: String to search.
   typeset str string x
   # Behavior here is not the same in bash vs ksh unless we escape special characters.
   str="$(str_escape_special_characters "${1}")"
   string="${2}"
   x="${string%%$str*}"
   if [[ "${x}" != "${string}" ]]; then
      echo "${#x} + 1" | bc -l
   else
      echo 0
   fi
}

function test_str_instr {
   str_instr "(" "'foo@host (dev,web)'" | assert_eq 11
   str_instr ")" "'foo@host (dev,web)'" | assert_eq 19
   str_instr "[" "'foo@host [dev,web]'" | assert_eq 11
   str_instr "]" "'foo@host [dev,web]'" | assert_eq 19
   str_instr "a" "abc" | assert_eq 1
   str_instr "z" "abc" | assert_eq 0
   str_instr "Eggs" "Green Eggs And Ham" | assert_eq 7
   str_instr "a" "" | assert_eq 0
   str_instr "" "" | assert_eq 0
   str_instr " " "Green Eggs" | assert_eq 6
   str_instr " " " Green "  | assert_eq 1
}

Belirsizlik! Ne olduğunu bağımlılık?
Peter Mortensen

"Str_escape_special_characters" işlevi. GitHub arcshell_str.sh dosyasındadır. arcshell.io sizi oraya götürür.
Ethan Post


0
msg="message"

function check {
    echo $msg | egrep [abc] 1> /dev/null

    if [ $? -ne 1 ];
    then 
        echo "found" 
    else 
        echo "not found" 
    fi
}

check

Bu a veya b veya c


0

Genel iğne samanlığı örneği değişkenlerle birlikte verilmektedir

#!/bin/bash

needle="a_needle"
haystack="a_needle another_needle a_third_needle"
if [[ $haystack == *"$needle"* ]]; then
    echo "needle found"
else
    echo "needle NOT found"
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.