Cara memeriksa apakah string berisi substring di Bash

2573

Saya memiliki string di Bash:

string="My string"

Bagaimana saya bisa menguji apakah itu berisi string lain?

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

Di mana ??operator tidak dikenal saya. Apakah saya menggunakan gema dan grep?

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

Itu terlihat agak canggung.

davidsheldon
sumber
4
Hai, jika string kosong salah, mengapa Anda menganggapnya canggung? Itu satu-satunya cara yang berhasil bagi saya, terlepas dari solusi yang diusulkan.
ericson.cepeda
1
Anda dapat menggunakan exprperintah di sini
cli__
4
Ini satu untuk kerang
posix

Jawaban:

3656

Anda dapat menggunakan jawaban Marcus (* wildcard) di luar pernyataan kasus, juga, jika Anda menggunakan tanda kurung ganda:

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

Perhatikan bahwa spasi di string harus ditempatkan di antara tanda kutip ganda, dan *wildcard harus di luar. Juga perhatikan bahwa operator pembanding sederhana digunakan (yaitu ==), bukan operator regex =~.

Adam Bellaire
sumber
127
Perhatikan juga bahwa Anda dapat membalik perbandingan dengan hanya beralih ke! = Dalam ujian. Terima kasih atas jawabannya!
Quinn Taylor
63
@Jonik: Anda mungkin kehilangan shebang atau memilikinya sebagai #!/bin/sh. Coba #!/bin/bashsaja.
Dijeda sampai pemberitahuan lebih lanjut.
10
Sisakan jarak antara tanda kurung dan isinya.
Paul Price
17
Anda tidak perlu mengutip variabel di dalam [[]]. Ini juga akan bekerja dengan baik: [[$ string == $ jarum ]] && echo ditemukan
Orwellophile
13
@Orwellophile Hati-hati! Anda hanya bisa menghilangkan tanda kutip ganda pada argumen pertama [[. Lihat ideone.com/ZSy1gZ
nyuszika7h
612

Jika Anda lebih suka pendekatan regex:

string='My string';

if [[ $string =~ "My" ]]
then
   echo "It's there!"
fi
Matt Tardiff
sumber
2
Harus mengganti regex egrep dalam skrip bash, ini bekerja dengan sempurna!
blast_hardcheese
114
The =~Operator sudah mencari seluruh string untuk pertandingan; yang ada .*di sini adalah asing. Juga, kutipan umumnya lebih baik daripada backslash:[[ $string =~ "My s" ]]
bukzor
16
@bukzor Kutipan berhenti bekerja di sini pada Bash 3.2+: tiswww.case.edu/php/chet/bash/FAQ E14) . Mungkin lebih baik untuk menetapkan ke variabel (menggunakan tanda kutip), lalu membandingkan. Seperti ini:re="My s"; if [[ $string =~ $re ]]
seanf
36
Tes jika TIDAK mengandung string: if [[ ! "abc" =~ "d" ]]benar.
KrisWebDev
1
Perhatikan bahwa urutan pengujian terjadi. Output dari baris kode berikut akan diteruskan 2.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
357

Saya tidak yakin tentang menggunakan pernyataan if, tetapi Anda bisa mendapatkan efek yang serupa dengan pernyataan kasus:

case "$string" in 
  *foo*)
    # Do stuff
    ;;
esac
Marcus Griep
sumber
76
Ini mungkin solusi terbaik karena dapat dibawa ke cangkang posix. (alias tanpa bashisme)
technosaurus
25
@ technosaurus Saya merasa agak aneh untuk mengkritik "bashism" dalam pertanyaan yang hanya memiliki tag bash :)
PP
39
@PP Ini bukan kritik karena preferensi solusi yang lebih universal daripada solusi yang lebih terbatas. Harap pertimbangkan bahwa, bertahun-tahun kemudian, orang-orang (seperti saya) akan mampir untuk mencari jawaban ini dan mungkin senang menemukan jawaban yang berguna dalam cakupan yang lebih luas daripada pertanyaan awal. Seperti yang mereka katakan di dunia Open Source: "pilihan itu bagus!"
Carl Smotricz
2
@ technosaurus, FWIW [[ $string == *foo* ]]juga berfungsi di beberapa versi sh yang sesuai dengan POSIX (mis. /usr/xpg4/bin/shpada Solaris 10) dan ksh (> = 88)
maxschlepzig
3
Abu Busybox tidak menangani tanda bintang di [[... sakelar kasusnya bekerja!
Ray Foss
232

stringContain varian (kompatibel atau case-independent)

Karena sebagian besar jawaban Stack Overflow ini memberi tahu tentang Bash , saya telah memposting fungsi Bash independen kasus di bagian paling bawah posting ini ...

Lagi pula, ini milik saya

Jawaban yang kompatibel

Karena sudah ada banyak jawaban menggunakan fitur spesifik Bash, ada cara untuk bekerja di bawah cangkang fitur yang lebih buruk, seperti BusyBox :

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

Dalam praktiknya, ini bisa memberi:

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

Ini diuji di bawah Bash, Dash , KornShell ( ksh) dan ash (BusyBox), dan hasilnya selalu:

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

Menjadi satu fungsi

Seperti yang ditanyakan oleh @EeroAaltonen di sini adalah versi demo yang sama, diuji di bawah cangkang yang sama:

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
}

Kemudian:

$ 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'.

Perhatikan: Anda harus melarikan diri atau melampirkan dua tanda kutip dan / atau tanda kutip ganda:

$ 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'.

Fungsi sederhana

Ini diuji di bawah BusyBox, Dash, dan, tentu saja Bash:

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

Kemudian sekarang:

$ 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

... Atau jika string yang dikirimkan dapat kosong, seperti yang ditunjukkan oleh @Sjlver, fungsi tersebut akan menjadi:

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

atau seperti yang disarankan oleh komentar Adrian Günter , menghindari -osakelar:

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

Fungsi final (sederhana):

Dan membalikkan tes untuk membuatnya berpotensi lebih cepat:

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

Dengan string kosong:

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

Tidak tergantung huruf besar (Hanya Bash!)

Untuk menguji string tanpa peduli case, cukup konversi setiap string ke huruf kecil:

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

Memeriksa:

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
F. Hauri
sumber
1
Ini akan lebih baik, jika Anda bisa mencari cara untuk menjalankannya.
Eero Aaltonen
2
@EeroAaltonen Bagaimana Anda menemukan fungsi (baru ditambahkan) saya?
F. Hauri
2
Aku tahu! Temukan . -nama "*" | xargs grep "myfunc" 2> / dev / null
eggmatters
6
Ini luar biasa karena sangat kompatibel. Satu bug, meskipun: Tidak berfungsi jika string tumpukan jerami kosong. Versi yang benar adalah string_contains() { [ -z "${2##*$1*}" ] && [ -n "$2" -o -z "$1" ]; } pemikiran terakhir: apakah string kosong berisi string kosong? Versi di atas hal-hal ya (karena -o -z "$1"bagian itu).
Sjlver
3
+1. Baik sekali! Bagi saya, saya mengubah urutan stringContain () {[-z "$ {1 ## * $ 2 *}"] && [-z "$ 2" -o -n "$ 1"]; }; "Cari di mana" "Temukan apa". Bekerja di busybox. Jawaban yang diterima di atas tidak berfungsi di busybox.
user3439968
149

Anda harus ingat bahwa skrip shell kurang dari bahasa dan lebih dari kumpulan perintah. Secara naluriah Anda berpikir bahwa "bahasa" ini mengharuskan Anda untuk mengikuti a ifdengan [a [[. Keduanya hanyalah perintah yang mengembalikan status keluar yang menunjukkan keberhasilan atau kegagalan (sama seperti setiap perintah lainnya). Untuk alasan itu saya akan menggunakan grep, dan bukan [perintah.

Kerjakan saja:

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

Sekarang Anda berpikir untuk ifmenguji status keluar dari perintah yang mengikutinya (lengkap dengan semi-colon), mengapa tidak mempertimbangkan kembali sumber string yang Anda uji?

## 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
#...

The -qpilihan membuat grep apa pun tidak output, karena kami hanya ingin kode kembali. <<<membuat shell memperluas kata berikutnya dan menggunakannya sebagai input ke perintah, versi satu-baris dari <<dokumen di sini (saya tidak yakin apakah ini standar atau Bashism).

Mark Baker
sumber
7
mereka disebut di sini string (3.6.7) Saya percaya ini adalah bashism
alex.pilon
10
kita juga bisa menggunakan Proses Substitusi if grep -q foo <(echo somefoothing); then
larsr
Catatan yang tidak echodapat diport, jika Anda mengirimkan variabel, gunakan printf '%s' "$stringsaja.
nyuszika7h
5
Biaya ini sangat mahal: melakukan grep -q foo <<<"$mystring"garpu impie 1 dan bashism dan echo $mystring | grep -q fooimpie 2 fork (satu untuk pipa dan yang kedua untuk menjalankan /path/to/grep)
F. Hauri
1
@BrunoBronosky echotanpa flag mungkin masih memiliki masalah portabilitas yang tidak terduga jika string argumen berisi urutan backslash. echo "nope\c"diharapkan pada beberapa platform berfungsi seperti echo -e "nope"pada beberapa lainnya. printf '%s' "nope"vsprintf '%s\n' 'nope\c'
tripleee
92

Jawaban yang diterima adalah yang terbaik, tetapi karena ada lebih dari satu cara untuk melakukannya, inilah solusi lain:

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

${var/search/replace}adalah $vardengan contoh pertama searchdiganti oleh replace, jika ditemukan (tidak berubah $var). Jika Anda mencoba untuk mengganti foodengan tidak ada, dan string telah berubah, maka jelas fooditemukan.

singkat
sumber
5
solusi ephemient di atas:> `if [" $ string "! =" $ {string / foo /} "]; lalu gema, "Itu ada di sana!" fi` berguna ketika menggunakan shell BusyBox ini abu . Solusi yang diterima tidak bekerja dengan BusyBox karena ekspresi reguler beberapa bash tidak diimplementasikan.
TPoschel
1
ketidaksetaraan perbedaan. Pikiran yang cukup aneh! I love it
nitinr708
1
kecuali string Anda adalah 'foo'
venimus
Saya sendiri yang menulis solusi ini (karena penerjemah saya tidak akan mengambil jawaban teratas) kemudian mencari yang lebih baik, tetapi ternyata ini!
BuvinJ
56

Jadi ada banyak solusi berguna untuk pertanyaan - tetapi mana yang tercepat / menggunakan sumber daya paling sedikit?

Tes berulang menggunakan frame ini:

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

Mengganti TEST setiap kali:

[[ $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 ada dalam jawaban F. Houri)

Dan untuk cekikikan:

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

Jadi pilihan substitusi sederhana dapat diprediksi menang, baik dalam tes diperpanjang atau kasus. Kasingnya portabel.

Menyalurkan ke 100000 greps diduga menyakitkan! Aturan lama tentang menggunakan utilitas eksternal tanpa perlu benar.

Paul Hedderly
sumber
4
Tolok ukur yang rapi. Meyakinkan saya untuk menggunakan [[ $b == *$a* ]].
Fisikawan Gila
2
Jika saya membaca ini dengan benar, casemenang dengan konsumsi waktu keseluruhan terkecil. Anda kehilangan tanda bintang setelahnya $b in *$a. Saya mendapatkan hasil yang sedikit lebih cepat [[ $b == *$a* ]]daripada dibandingkan casedengan bug yang diperbaiki, tetapi itu bisa bergantung pada faktor-faktor lain juga, tentu saja.
tripleee
1
ideone.com/5roEVt melakukan percobaan dengan beberapa bug tambahan diperbaiki dan menguji skenario yang berbeda (di mana string sebenarnya tidak ada dalam string yang lebih panjang). Hasilnya sebagian besar serupa; [[ $b == *$a* ]]cepat dan casehampir sama cepat (dan menyenangkan POSIX-kompatibel).
tripleee
28

Ini juga berfungsi:

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

Dan tes negatifnya adalah:

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

Saya kira gaya ini sedikit lebih klasik - kurang tergantung pada fitur Bash shell.

The --argumen adalah murni paranoia POSIX, digunakan untuk dilindungi terhadap string masukan mirip dengan pilihan, seperti --abcatau -a.

Catatan: Dalam loop ketat kode ini akan jauh lebih lambat daripada menggunakan fitur internal Bash shell, karena satu (atau dua) proses terpisah akan dibuat dan dihubungkan melalui pipa.

kevinarpe
sumber
5
... tetapi OP tidak mengatakan versi bash mana; misalnya, bash yang lebih lama (seperti yang sering dimiliki solaris) mungkin tidak menyertakan fitur bash yang lebih baru ini. (Saya telah mengalami masalah yang sebenarnya ini (pencocokan pola bash tidak diterapkan) pada solaris w / bash 2.0)
michael
2
echotidak dapat diport, Anda harus menggunakan printf '%s' "$haystacksebagai gantinya.
nyuszika7h
2
Tidak, hindari echosama sekali untuk apa pun kecuali teks literal tanpa lolos yang tidak dimulai dengan a -. Ini mungkin bekerja untuk Anda, tetapi ini tidak portabel. Bahkan bash echoakan berperilaku berbeda tergantung pada apakah xpg_echoopsi diatur. PS: Saya lupa menutup kutipan ganda dalam komentar saya sebelumnya.
nyuszika7h
1
@ kevinarpe Saya tidak yakin, --tidak tercantum dalam spesifikasi POSIX untukprintf , tetapi Anda harus printf '%s' "$anything"tetap menggunakan , untuk menghindari masalah jika $anythingmengandung %karakter.
nyuszika7h
1
@ kevinarpe Berdasarkan itu, mungkin itu.
nyuszika7h
21

Bash 4+ contoh. Catatan: tidak menggunakan tanda kutip akan menyebabkan masalah ketika kata-kata mengandung spasi, dll. Selalu kutip di Bash, IMO.

Berikut adalah beberapa contoh Bash 4+:

Contoh 1, periksa 'ya' dalam string (case-sensitive):

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

Contoh 2, periksa 'ya' dalam string (case-sensitive):

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

Contoh 3, periksa 'ya' dalam string (peka huruf besar kecil):

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

Contoh 4, periksa 'ya' dalam string (peka huruf besar kecil):

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

Contoh 5, pencocokan tepat (peka huruf besar-kecil):

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

Contoh 6, kecocokan persis (tidak sensitif huruf besar):

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

Contoh 7, kecocokan persis:

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

Contoh 8, wildcard match .ext (case-sensitive):

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

Nikmati.

Mike Q
sumber
17

Bagaimana dengan ini:

text="   <tag>bmnmn</tag>  "
if [[ "$text" =~ "<tag>" ]]; then
   echo "matched"
else
   echo "not matched"
fi
bn.
sumber
2
= ~ untuk pencocokan regexp, karena itu terlalu kuat untuk tujuan OP.
16

Seperti yang disebutkan Paul dalam perbandingan kinerjanya:

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

Ini sesuai dengan POSIX seperti 'case "$ string" pada' jawaban yang diberikan oleh Marcus , tetapi sedikit lebih mudah dibaca daripada jawaban pernyataan kasus. Perhatikan juga bahwa ini akan jauh lebih lambat daripada menggunakan pernyataan kasus. Seperti yang ditunjukkan Paul, jangan menggunakannya dalam satu lingkaran.

Samuel
sumber
11

Jawaban Stack Overflow ini adalah satu-satunya yang menjebak karakter spasi dan dash:

# For null cmd arguments checking   
to_check=' -t'
space_n_dash_chars=' -'
[[ $to_check == *"$space_n_dash_chars"* ]] && echo found
Yordan Georgiev
sumber
Ini adalah jawaban untuk pertanyaan yang sama.
Peter Mortensen
9
[[ $string == *foo* ]] && echo "It's there" || echo "Couldn't find"
Jahid
sumber
Saya akan menambahkan bahwa echo "Couldn't findpernyataan di akhir adalah trik yang bagus untuk mengembalikan 0 status keluar untuk perintah yang cocok ini.
nicodjimenez
@nicodjimenez Anda tidak dapat menargetkan status keluar lagi dengan solusi ini. Status keluar ditelan oleh pesan status ...
Jahid
1
Itulah yang saya maksudkan ... Jika Anda tidak memilikinya || echo "Couldn't find"maka Anda akan mengembalikan status keluar kesalahan jika tidak ada kecocokan, yang mungkin tidak Anda inginkan jika Anda menjalankan pipa CI misalnya di mana Anda ingin semua perintah kembali status keluar tidak salah
nicodjimenez
9

Satu adalah:

[ $(expr $mystring : ".*${search}.*") -ne 0 ] && echo 'yes' ||  echo 'no'
chemila
sumber
2
expradalah salah satu dari utilitas swiss-army-knife yang biasanya dapat melakukan apa pun yang perlu Anda lakukan, setelah Anda mengetahui bagaimana melakukannya, tetapi sekali diterapkan, Anda tidak akan pernah ingat mengapa atau bagaimana ia melakukan apa yang dilakukannya, sehingga Anda jangan pernah menyentuhnya lagi, dan berharap itu tidak pernah berhenti melakukan apa yang dilakukannya.
michael
@AloisMahdal Saya tidak pernah memilih, saya hanya mendalilkan mengapa downvote diberikan. Komentar peringatan. Saya memang menggunakan expr, pada kesempatan yang jarang, ketika portabilitas mencegah penggunaan bash (mis., Perilaku tidak konsisten di versi yang lebih lama), tr (tidak konsisten di mana-mana) atau sed (kadang-kadang terlalu lambat). Tapi dari pengalaman pribadi, setiap kali membaca ulang expr-ism ini , saya harus kembali ke halaman manual. Jadi, saya hanya akan berkomentar bahwa setiap penggunaan exprkomentar ...
michael
1
Ada saat ketika yang Anda miliki hanyalah kulit Bourne yang asli. Itu tidak memiliki beberapa fitur yang biasanya diperlukan, jadi alat suka exprdan testdiimplementasikan untuk melakukannya. Di zaman sekarang ini, biasanya ada alat yang lebih baik, banyak dari mereka dibangun ke dalam shell modern. Saya kira testmasih tergantung di sana, tetapi tampaknya tidak ada yang hilang expr.
tripleee
6

Saya suka sed.

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

Edit, Logika:

  • Gunakan sed untuk menghapus turunan dari string

  • Jika string baru berbeda dari string lama, substring ada

mengendarai
sumber
2
Silakan tambahkan beberapa penjelasan. Memberi logika yang mendasarinya lebih penting daripada hanya memberikan kode, karena itu membantu OP dan pembaca lain memperbaiki sendiri masalah ini dan yang serupa
Zulan
5

grep -q berguna untuk tujuan ini.

Penggunaan yang sama awk:

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

Keluaran:

Tidak ditemukan

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

Keluaran:

Ditemukan

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

nyuszika7h
sumber
3
echotidak dapat diport, Anda harus menggunakan printf '%s' "$string"sebagai gantinya. Saya mengedit jawaban karena pengguna tampaknya tidak ada lagi.
nyuszika7h
Dengan cara apa echotidak portabel, @ nyuszika7h?
starbeamrainbowlabs
5

Saya menemukan sangat membutuhkan fungsi ini, jadi saya menggunakan fungsi shell buatan saya .bashrcseperti ini yang memungkinkan saya untuk menggunakannya kembali sesering yang saya butuhkan, dengan nama yang mudah diingat:

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

Untuk menguji apakah $string1(katakanlah, abc ) terkandung dalam $string2(katakanlah, 123abcABC ) Saya hanya perlu menjalankan stringinstring "$string1" "$string2"dan memeriksa nilai pengembalian, misalnya

stringinstring "$str1" "$str2"  &&  echo YES  ||  echo NO
Kurt Pfeifle
sumber
[["$ str" == $ substr ]] && echo YES || echo NO
elyase
Saya cukup yakin xperetasan hanya diperlukan untuk kerang yang sangat lama.
nyuszika7h
5

File .bash_profile saya dan bagaimana saya menggunakan grep:

Jika variabel lingkungan PATH menyertakan dua bindirektori saya , jangan tambahkan mereka,

# .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
Leslie Satenstein
sumber
1
Apakah ini jawaban?
codeforester
Suara positif. mengapa repot-repot belajar bagaimana Bash melakukannya ketika grep, jauh lebih kuat, kemungkinan besar akan tersedia. juga memperpanjang sedikit lebih jauh dengan pencocokan terhadap daftar pola: grep -q -E 'pattern1|...|patternN'.
Mohamed Bana
4

Perpanjangan pertanyaan dijawab di sini Bagaimana Anda tahu jika sebuah string berisi string lain di POSIX sh? :

Solusi ini bekerja dengan karakter khusus:

# 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*"
Alex Skrypnyk
sumber
Tes contains "-n" "n"tidak berfungsi di sini, karena echo -nakan menelan -nopsi! Perbaikan populer untuk itu adalah untuk digunakan printf "%s\n" "$string"sebagai gantinya.
joeytwiddle
sempurna, string dipecahkan berisi ruang
dengApro
4

Karena pertanyaan POSIX / BusyBox ditutup tanpa memberikan jawaban yang tepat (IMHO), saya akan memposting jawaban di sini.

Jawaban sesingkat mungkin adalah:

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

atau

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

Perhatikan bahwa hash ganda adalah wajib dengan beberapa kerang ( ash). Di atas akan mengevaluasi [ stringvalue ]ketika substring tidak ditemukan. Ia tidak mengembalikan kesalahan. Ketika substring ditemukan hasilnya kosong dan mengevaluasi [ ]. Ini akan membuang kode kesalahan 1 karena string sepenuhnya diganti (karena *).

Sintaks terpendek yang lebih umum:

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

atau

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

Yang lainnya:

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

atau

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

Perhatikan tanda sama dengan tunggal !

Aksioma Kelima
sumber
3

Pencocokan kata yang tepat:

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

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

Coba oobash.

Ini adalah pustaka string gaya OO untuk Bash 4. Ia memiliki dukungan untuk umlaut Jerman. Itu ditulis dalam Bash.

Banyak fungsi yang tersedia: -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, dan -zfill.

Lihatlah contoh berisi :

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

oobash tersedia di Sourceforge.net .

andreas
sumber
2

Saya menggunakan fungsi ini (satu ketergantungan tidak termasuk tetapi jelas). Itu melewati tes yang ditunjukkan di bawah ini. Jika fungsi mengembalikan nilai> 0 maka string ditemukan. Anda bisa dengan mudah mengembalikan 1 atau 0 sebagai gantinya.

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
}
Ethan Post
sumber
Ketegangan! Apa adalah ketergantungan?
Peter Mortensen
Fungsi "str_escape_special_characters". Itu ada di file GitHub arcshell_str.sh. arcshell.io akan membawa Anda ke sana.
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

Ini akan menemukan terjadinya a atau b atau c

BobMonk
sumber
0

Contoh tumpukan jerami jarum generik mengikuti variabel

#!/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
Pipo
sumber