Saya menjawab pertanyaan ini pada SuperUser yang merupakan sesuatu yang berkaitan dengan jenis ekspresi Reguler yang digunakan saat menerima keluaran.
Jawaban yang saya berikan adalah ini:
tail -f log | grep "some_string.*some_string"
Dan kemudian, Dalam tiga komentar untuk jawaban saya @ Bob menulis ini:
.*
serakah dan mungkin menangkap lebih dari yang Anda inginkan..*?
biasanya lebih baik.
Lalu ini,
itu
?
adalah pengubah aktif*
, menjadikannya malas bukannya default serakah. Dengan asumsi PCRE.
Saya mencari di Google PCRE
, tetapi tidak bisa mendapatkan apa arti dari ini dalam jawaban saya?
dan akhirnya ini,
Saya juga harus menunjukkan bahwa ini adalah regex (grep melakukan POSIX regex secara default), bukan shell glob.
Saya hanya tahu apa itu Regex dan penggunaannya yang sangat mendasar dalam perintah grep. Jadi, saya tidak bisa mendapatkan salah satu dari 3 komentar itu dan saya memiliki pertanyaan ini dalam pikiran:
- Apa perbedaan dalam penggunaan
.*?
vs.*
? - Mana yang lebih baik dan dalam keadaan apa? Tolong berikan contoh.
Juga akan sangat membantu untuk memahami komentar, Jika ada yang bisa
PEMBARUAN: Sebagai jawaban atas pertanyaan. Apa perbedaan Regex dari Shell Glob? @ Kusalananda memberikan tautan ini dalam komentarnya.
CATATAN: Jika perlu, Harap baca jawaban saya untuk pertanyaan ini sebelum menjawab untuk merujuk pada konteks.
sumber
.*
vs..*?
Pertanyaan "perbedaan antara ekspresi reguler dan gumpalan shell" telah ditanggapi di situs ini.Jawaban:
Ashok sudah menunjukkan perbedaan antara
.*
dan.*?
, jadi saya hanya akan memberikan beberapa informasi tambahan.grep
(dengan asumsi versi GNU) mendukung 4 cara untuk mencocokkan string:grep
menggunakan BRE secara default.BRE dan ERE didokumentasikan dalam bab Ekspresi Reguler POSIX dan PCRE didokumentasikan di situs resminya . Harap dicatat bahwa fitur dan sintaksis dapat bervariasi di antara implementasi.
Layak dikatakan bahwa BRE atau ERE tidak mendukung kemalasan :
Jadi jika Anda ingin menggunakan fitur itu, Anda harus menggunakan PCRE sebagai gantinya:
Edit 1
.*
digunakan untuk mencocokkan dengan pola "terpanjang" 1 yang mungkin..*?
digunakan untuk mencocokkan pola "terpendek" 1 mungkin.Dalam pengalaman saya, perilaku yang paling dicari biasanya yang kedua.
Misalnya, katakanlah kami memiliki string berikut dan kami hanya ingin mencocokkan tag html 2 , bukan konten di antara mereka:
Sekarang bandingkan
.*
vs.*?
:1. Arti "terpanjang" dan "terpendek" dalam konteks regex agak rumit, seperti yang ditunjukkan Kusalananda . Rujuk ke dokumentasi resmi untuk informasi lebih lanjut.
2. Tidak disarankan untuk mem-parsing html dengan regex . Ini hanya contoh untuk tujuan pendidikan, jangan menggunakannya dalam produksi.
sumber
.*
vs.*?
?Misalkan saya mengambil string seperti:
can cats eat plants?
Menggunakan serakah
c.*s
akan cocok dengan seluruh string sejak dimulai denganc
dan berakhir dengans
, sebagai operator serakah itu terus cocok hingga kemunculan terakhir dari s.Sedangkan menggunakan lazy
c.*?s
hanya akan cocok sampai kemunculan pertamas
ditemukan, yaitu stringcan cats
.Dari contoh di atas, Anda mungkin dapat menyimpulkan bahwa:
"Serakah" berarti mencocokkan string yang terpanjang. "Malas" berarti mencocokkan string sesingkat mungkin. Menambahkan
?
ke quantifier seperti*
,+
,?
, atau{n,m}
merek itu malas.sumber
cats
, jadi itu tidak memberlakukan "sesingkat mungkin" secara ketat dalam arti itu.String dapat dicocokkan dengan beberapa cara (dari yang sederhana ke yang lebih kompleks):
Sebagai string statis (Asumsikan var = 'Hello World!'):
shell
[ "$var" = "Hello World!" ] && echo yes
grep
echo "$var" | grep -F "Hello"
bash
grep -F "Hello" <<<"$var"
Sebagai gumpalan:
shell
echo ./*
# daftarkan semua file dalam pwd.
shell
case $var in (*Worl*) echo yes;; (*) echo no;; esac
bash
[[ "$var" == *"Worl"* ]] && echo yes
Ada gumpalan dasar dan diperpanjang. The
case
contoh menggunakan gumpalan dasar. Contoh bash[[
menggunakan glob diperpanjang. Pencocokan file pertama bisa mendasar atau diperluas pada beberapa shell seperti pengaturanextglob
di bash. Keduanya identik dalam hal ini. Grep tidak dapat menggunakan gumpalan.Tanda bintang di sebuah bola berarti sesuatu yang berbeda dari tanda bintang di sebuah regex :
gumpal
* matches any number (including none) of
setiap karakter .regex
* matches any number (including none) of the
elemen sebelumnya .Sebagai ungkapan reguler dasar (BRE):
sed
echo "$var" | sed 's/W.*d//'
# print: Halo!
grep
grep -o 'W.*d' <<<"$var"
# print World!
Tidak ada BRE dalam cangkang (dasar) atau awk.
Ekspresi reguler yang diperluas (ERE):
bash
[[ "$var" =~ (H.*l) ]]
# match: Hello Worl
sed
echo "$var" | sed -E 's/(d|o)//g'
# print: Hell Wrl!
awk
awk '/W.*d/{print $1}' <<<"$var"
# print: Hello
grep
grep -oE 'H.*l' <<<"$var"
# print: Hello Worl
Ekspresi Reguler Kompatibel yang Kompatibel:
grep
grep -oP 'H.*?l
# print: Hel
Hanya dalam PCRE a
*?
memiliki beberapa arti sintaksis spesifik.Itu membuat asterisk malas (ungreedy): Kemalasan Alih-alih Keserakahan .
Ini hanya puncak gunung es, ada yang serakah, malas , dan jinak atau posesif . Ada juga lookahead dan lookbehind tetapi itu tidak berlaku untuk tanda bintang
*
.Ada alternatif untuk mendapatkan efek yang sama dengan regex yang tidak serakah:
Idenya sangat sederhana: jangan gunakan titik
.
, meniadakan karakter berikutnya untuk mencocokkan[^o]
. Dengan tag web:Di atas harus sepenuhnya menjelaskan semua komentar @ Bob 3. Parafrase:
.*
serakah.*?
tidak.Pertanyaan
Apa perbedaan dalam penggunaan. ? vs. ?
.*?
hanya valid dalam sintaks PCRE..*
lebih portabel.[^a]*
Mana yang lebih baik dan dalam keadaan apa? Tolong berikan contoh.
Lebih baik? Itu tergantung tujuannya. Tidak ada yang lebih baik, masing-masing berguna untuk tujuan yang berbeda. Saya telah memberikan beberapa contoh di atas. Apakah kamu butuh lebih?
sumber