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.
expr
perintah di siniJawaban:
Anda dapat menggunakan jawaban Marcus (* wildcard) di luar pernyataan kasus, juga, jika Anda menggunakan tanda kurung ganda:
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=~
.sumber
#!/bin/sh
. Coba#!/bin/bash
saja.[[
. Lihat ideone.com/ZSy1gZJika Anda lebih suka pendekatan regex:
sumber
=~
Operator sudah mencari seluruh string untuk pertandingan; yang ada.*
di sini adalah asing. Juga, kutipan umumnya lebih baik daripada backslash:[[ $string =~ "My s" ]]
E14)
. Mungkin lebih baik untuk menetapkan ke variabel (menggunakan tanda kutip), lalu membandingkan. Seperti ini:re="My s"; if [[ $string =~ $re ]]
if [[ ! "abc" =~ "d" ]]
benar.number=2; if [[ "1, 2, 4, 5" = *${number}* ]]; then echo forward $number; fi; if [[ *${number}* = "1, 2, 4, 5" ]]; then echo backwards $number; fi;
Saya tidak yakin tentang menggunakan pernyataan if, tetapi Anda bisa mendapatkan efek yang serupa dengan pernyataan kasus:
sumber
[[ $string == *foo* ]]
juga berfungsi di beberapa versi sh yang sesuai dengan POSIX (mis./usr/xpg4/bin/sh
pada Solaris 10) dan ksh (> = 88)[[
... sakelar kasusnya bekerja!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 :
Dalam praktiknya, ini bisa memberi:
Ini diuji di bawah Bash, Dash , KornShell (
ksh
) dan ash (BusyBox), dan hasilnya selalu:Menjadi satu fungsi
Seperti yang ditanyakan oleh @EeroAaltonen di sini adalah versi demo yang sama, diuji di bawah cangkang yang sama:
Kemudian:
Perhatikan: Anda harus melarikan diri atau melampirkan dua tanda kutip dan / atau tanda kutip ganda:
Fungsi sederhana
Ini diuji di bawah BusyBox, Dash, dan, tentu saja Bash:
Kemudian sekarang:
... Atau jika string yang dikirimkan dapat kosong, seperti yang ditunjukkan oleh @Sjlver, fungsi tersebut akan menjadi:
atau seperti yang disarankan oleh komentar Adrian Günter , menghindari
-o
sakelar:Fungsi final (sederhana):
Dan membalikkan tes untuk membuatnya berpotensi lebih cepat:
Dengan string kosong:
Tidak tergantung huruf besar (Hanya Bash!)
Untuk menguji string tanpa peduli case, cukup konversi setiap string ke huruf kecil:
Memeriksa:
sumber
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).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
if
dengan[
a[[
. Keduanya hanyalah perintah yang mengembalikan status keluar yang menunjukkan keberhasilan atau kegagalan (sama seperti setiap perintah lainnya). Untuk alasan itu saya akan menggunakangrep
, dan bukan[
perintah.Kerjakan saja:
Sekarang Anda berpikir untuk
if
menguji status keluar dari perintah yang mengikutinya (lengkap dengan semi-colon), mengapa tidak mempertimbangkan kembali sumber string yang Anda uji?The
-q
pilihan 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).sumber
if grep -q foo <(echo somefoothing); then
echo
dapat diport, jika Anda mengirimkan variabel, gunakanprintf '%s' "$string
saja.grep -q foo <<<"$mystring"
garpu impie 1 dan bashism danecho $mystring | grep -q foo
impie 2 fork (satu untuk pipa dan yang kedua untuk menjalankan/path/to/grep
)echo
tanpa flag mungkin masih memiliki masalah portabilitas yang tidak terduga jika string argumen berisi urutan backslash.echo "nope\c"
diharapkan pada beberapa platform berfungsi sepertiecho -e "nope"
pada beberapa lainnya.printf '%s' "nope"
vsprintf '%s\n' 'nope\c'
Jawaban yang diterima adalah yang terbaik, tetapi karena ada lebih dari satu cara untuk melakukannya, inilah solusi lain:
${var/search/replace}
adalah$var
dengan contoh pertamasearch
diganti olehreplace
, jika ditemukan (tidak berubah$var
). Jika Anda mencoba untuk menggantifoo
dengan tidak ada, dan string telah berubah, maka jelasfoo
ditemukan.sumber
Jadi ada banyak solusi berguna untuk pertanyaan - tetapi mana yang tercepat / menggunakan sumber daya paling sedikit?
Tes berulang menggunakan frame ini:
Mengganti TEST setiap kali:
(doContain ada dalam jawaban F. Houri)
Dan untuk cekikikan:
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.
sumber
[[ $b == *$a* ]]
.case
menang dengan konsumsi waktu keseluruhan terkecil. Anda kehilangan tanda bintang setelahnya$b in *$a
. Saya mendapatkan hasil yang sedikit lebih cepat[[ $b == *$a* ]]
daripada dibandingkancase
dengan bug yang diperbaiki, tetapi itu bisa bergantung pada faktor-faktor lain juga, tentu saja.[[ $b == *$a* ]]
cepat dancase
hampir sama cepat (dan menyenangkan POSIX-kompatibel).Ini juga berfungsi:
Dan tes negatifnya adalah:
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--abc
atau-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.
sumber
echo
tidak dapat diport, Anda harus menggunakanprintf '%s' "$haystack
sebagai gantinya.echo
sama sekali untuk apa pun kecuali teks literal tanpa lolos yang tidak dimulai dengan a-
. Ini mungkin bekerja untuk Anda, tetapi ini tidak portabel. Bahkan bashecho
akan berperilaku berbeda tergantung pada apakahxpg_echo
opsi diatur. PS: Saya lupa menutup kutipan ganda dalam komentar saya sebelumnya.--
tidak tercantum dalam spesifikasi POSIX untukprintf
, tetapi Anda harusprintf '%s' "$anything"
tetap menggunakan , untuk menghindari masalah jika$anything
mengandung%
karakter.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):
Contoh 2, periksa 'ya' dalam string (case-sensitive):
Contoh 3, periksa 'ya' dalam string (peka huruf besar kecil):
Contoh 4, periksa 'ya' dalam string (peka huruf besar kecil):
Contoh 5, pencocokan tepat (peka huruf besar-kecil):
Contoh 6, kecocokan persis (tidak sensitif huruf besar):
Contoh 7, kecocokan persis:
Contoh 8, wildcard match .ext (case-sensitive):
Nikmati.
sumber
Bagaimana dengan ini:
sumber
Seperti yang disebutkan Paul dalam perbandingan kinerjanya:
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.
sumber
Jawaban Stack Overflow ini adalah satu-satunya yang menjebak karakter spasi dan dash:
sumber
sumber
echo "Couldn't find
pernyataan di akhir adalah trik yang bagus untuk mengembalikan 0 status keluar untuk perintah yang cocok ini.|| 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 salahSatu adalah:
sumber
expr
adalah 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.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 ulangexpr
-ism ini , saya harus kembali ke halaman manual. Jadi, saya hanya akan berkomentar bahwa setiap penggunaanexpr
komentar ...expr
dantest
diimplementasikan untuk melakukannya. Di zaman sekarang ini, biasanya ada alat yang lebih baik, banyak dari mereka dibangun ke dalam shell modern. Saya kiratest
masih tergantung di sana, tetapi tampaknya tidak ada yang hilangexpr
.Saya suka sed.
Edit, Logika:
Gunakan sed untuk menghapus turunan dari string
Jika string baru berbeda dari string lama, substring ada
sumber
grep -q
berguna untuk tujuan ini.Penggunaan yang sama
awk
:Keluaran:
Keluaran:
Sumber asli: http://unstableme.blogspot.com/2008/06/bash-search-letter-in-string-awk.html
sumber
echo
tidak dapat diport, Anda harus menggunakanprintf '%s' "$string"
sebagai gantinya. Saya mengedit jawaban karena pengguna tampaknya tidak ada lagi.echo
tidak portabel, @ nyuszika7h?Saya menemukan sangat membutuhkan fungsi ini, jadi saya menggunakan fungsi shell buatan saya
.bashrc
seperti ini yang memungkinkan saya untuk menggunakannya kembali sesering yang saya butuhkan, dengan nama yang mudah diingat:Untuk menguji apakah
$string1
(katakanlah, abc ) terkandung dalam$string2
(katakanlah, 123abcABC ) Saya hanya perlu menjalankanstringinstring "$string1" "$string2"
dan memeriksa nilai pengembalian, misalnyasumber
x
peretasan hanya diperlukan untuk kerang yang sangat lama.File .bash_profile saya dan bagaimana saya menggunakan grep:
Jika variabel lingkungan PATH menyertakan dua
bin
direktori saya , jangan tambahkan mereka,sumber
grep -q -E 'pattern1|...|patternN'
.Perpanjangan pertanyaan dijawab di sini Bagaimana Anda tahu jika sebuah string berisi string lain di POSIX sh? :
Solusi ini bekerja dengan karakter khusus:
sumber
contains "-n" "n"
tidak berfungsi di sini, karenaecho -n
akan menelan-n
opsi! Perbaikan populer untuk itu adalah untuk digunakanprintf "%s\n" "$string"
sebagai gantinya.Karena pertanyaan POSIX / BusyBox ditutup tanpa memberikan jawaban yang tepat (IMHO), saya akan memposting jawaban di sini.
Jawaban sesingkat mungkin adalah:
atau
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:
atau
Yang lainnya:
atau
Perhatikan tanda sama dengan tunggal !
sumber
Pencocokan kata yang tepat:
sumber
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 :
oobash tersedia di Sourceforge.net .
sumber
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.
sumber
Ini adalah jawaban yang sama dengan https://stackoverflow.com/a/229585/11267590 . Tapi gaya simpel dan juga POSIX Compliant.
sumber
Ini akan menemukan terjadinya a atau b atau c
sumber
Contoh tumpukan jerami jarum generik mengikuti variabel
sumber