Bagaimana cara kerja ekspresi reguler?


30

Katakanlah Anda memiliki dokumen dengan esai yang ditulis. Anda ingin mengurai esai ini hanya memilih kata-kata tertentu. Keren.

Apakah menggunakan ekspresi reguler lebih cepat daripada mem-parsing baris demi baris file dan kata demi kata mencari kecocokan? kalau begitu, bagamana itu bekerja? Bagaimana Anda bisa lebih cepat daripada melihat setiap kata?


5
Anda berasumsi (menyiratkan bukti nol) bahwa ekspresi reguler akan lebih cepat tetapi Anda tidak tahu mengapa itu? Mungkin Anda harus mempertimbangkan kembali asumsi Anda.
pdr

3
dengan demikian, anggapan. jika saya punya bukti, itu tidak akan menjadi satu, kan?
lazeR

4
Itu bukan intinya. Intinya adalah apa yang membawa Anda ke asumsi itu ... Anda tidak perlu bukti untuk pertanyaan Anda, tetapi Anda memang perlu alasan untuk asumsi Anda.
yannis

1
err, bukankah setiap karakter dari string input hanya memindahkan mesin status ke status berikutnya. Saya tidak melihat bagaimana orang bisa memperlambat operasi itu ...
tp1

2
Saya tidak yakin tentang lebih cepat, tetapi alasan utama saya untuk menggunakan ekspresi reguler adalah karena keanggunan pola pencocokan yang kompleks, Anda tidak akan menemukan cara yang lebih baik untuk mengartikulasikannya dalam lingkungan pengkodean.
Mantorok

Jawaban:


47

Bagaimana cara kerjanya?

Lihatlah teori automata

Singkatnya, setiap ekspresi reguler memiliki otomat terbatas yang setara dan dapat dikompilasi dan dioptimalkan untuk otomat terbatas. Algoritma yang terlibat dapat ditemukan di banyak buku kompiler. Algoritma ini digunakan oleh program unix seperti awk dan grep.

Namun, sebagian besar bahasa pemrograman modern (Perl, Python, Ruby, Java (dan bahasa berbasis JVM), C #) tidak menggunakan pendekatan ini. Mereka menggunakan pendekatan backtracking rekursif, yang mengkompilasi ekspresi reguler menjadi pohon atau urutan konstruksi yang mewakili berbagai sub-bongkahan dari ekspresi reguler. Kebanyakan sintaks "ekspresi reguler" modern menawarkan referensi-ulang yang berada di luar kelompok bahasa reguler (mereka tidak memiliki representasi dalam automata terbatas), yang secara sepele dapat diterapkan dalam pendekatan backtracking rekursif.

Optimalisasi biasanya menghasilkan mesin keadaan yang lebih efisien. Sebagai contoh: pertimbangkan aaaab | aaaac | aaaad, seorang programmer normal bisa mendapatkan implementasi pencarian yang sederhana tetapi kurang efisien (membandingkan tiga string secara terpisah) tepat dalam sepuluh menit; tetapi menyadari itu setara dengan aaaa [bcd], pencarian yang lebih baik dapat dilakukan dengan mencari empat 'a' lalu menguji karakter ke-5 terhadap [b, c, d]. Proses optimasi adalah salah satu pekerjaan rumahan kompiler saya bertahun-tahun yang lalu, jadi saya berasumsi itu juga di kebanyakan mesin ekspresi reguler modern.

Di sisi lain, mesin negara memang memiliki beberapa keuntungan ketika mereka menerima string karena mereka menggunakan lebih banyak ruang dibandingkan dengan "implementasi sepele". Pertimbangkan program untuk melepaskan kutip dari string SQL, yaitu: 1) dimulai dan diakhiri dengan tanda kutip tunggal; 2) tanda kutip tunggal diloloskan oleh dua kutip tunggal berturut-turut. Jadi: input ['a' ''] harus menghasilkan output [a ']. Dengan mesin negara, tanda kutip tunggal berturut-turut ditangani oleh dua negara. Kedua status ini melayani tujuan mengingat histori input sehingga setiap karakter input diproses tepat hanya sekali, seperti yang diilustrasikan berikut:

...
S1->'->S2
S1->*->S1, output *, * can be any other character 
S2->'->S1, output '
S2->*->END, end the current string

Jadi, menurut pendapat saya, ekspresi reguler mungkin lebih lambat dalam beberapa kasus sepele, tetapi biasanya lebih cepat daripada algoritma pencarian yang dibuat secara manual, mengingat fakta bahwa pengoptimalan tidak dapat dilakukan secara andal oleh manusia.

(Bahkan dalam kasus sepele seperti mencari string, mesin pintar dapat mengenali jalur tunggal di peta keadaan dan mengurangi bagian itu menjadi perbandingan string sederhana dan menghindari mengelola negara.)

Mesin tertentu dari kerangka / pustaka mungkin lambat karena mesin melakukan banyak hal lain yang biasanya tidak dibutuhkan oleh programmer. Contoh: kelas Regex di .NET membuat banyak objek termasuk Pertandingan, Grup dan Capture.


2
Saya sendiri tidak bisa mengatakannya dengan lebih baik. Satu-satunya hal yang akan saya tambahkan: Ekspresi Reguler juga dapat menggantikan programmer yang malas. Dalam contoh yang Anda sebutkan aaaab|aaaac|aaaadvs aaaa[bcd]. Perlu dinyatakan secara eksplisit bahwa keduanya setara secara matematis dan menghasilkan DFA yang sama, sehingga memberi kebebasan lebih banyak kepada programmer untuk mewakili ekspresi reguler dengan cara yang masuk akal (bukan bahwa ini adalah praktik umum, tetapi ... Anda tahu). ..
riwalk

Terima kasih, ini benar-benar masuk akal berkat kelas automata yang saya ambil
lazeR

Apakah ini contoh masalah sepele di mana regex berlebihan ?: stackoverflow.com/questions/18955099/…
Menelaos Bakopoulos

17

Ekspresi reguler hanya terlihat cepat karena Anda memiliki komputer yang cepat.

Kembali pada 1980-an ketika 1 MIPS adalah komputer yang cepat, ekspresi reguler adalah area yang cukup besar dari kekhawatiran, kekhawatiran, dan penelitian karena mereka lambat dan jelek serta komputasi intensif. Pengembangan algoritma pintar diikuti dan membantu - tetapi untuk semua tujuan praktis hari ini Anda melihat keajaiban mesin cepat melapisi celah-celah.


2
Jika Anda hanya mencari satu kata, kedua metode ini sama (atau regexp sedikit lebih lambat). Tetapi mengingat ekspresi yang kompleks (dan teks dengan ukuran yang cukup besar), ekspresi reguler mungkin akan lebih cepat daripada pencarian sederhana (dengan asumsi Anda menulis pencarian sederhana hanya (Anda selalu dapat menulis pencarian kompleks yang secepat)). Sekarang cuaca itu penting adalah pertanyaan yang terlalu umum dan Anda harus melihatnya berdasarkan kasus per kasus.
Martin York

3
-1. Teori ekspresi reguler berawal dari 50-an dan berperan penting dalam menciptakan analisis leksikal (dan dengan ekstensi, penyusun). Mereka membuat mesin negara yang sangat efisien yang (terbukti) menggunakan negara dengan jumlah paling sedikit. Mesin negara yang dihasilkan dapat mencocokkan pola kompleks lebih cepat dari apa pun yang Anda bisa tulis dengan tangan. Mereka terlihat cepat karena mereka cepat.
riwalk

Mungkin saya sedikit ketinggalan poin. Mereka mungkin "cepat" tapi itu semua relatif - masih ada banyak pekerjaan yang harus dilakukan. Beberapa jawaban lain di sini juga bisa dibaca.
cepat_now

Apakah jawaban ini relevan dengan pertanyaan? dan bagaimana 13 upvotes?
Sadan dan

7

Menurut Anda mengapa mereka lebih cepat daripada mencari dokumen?

Ada beberapa trik yang bisa Anda lakukan, misalnya. Jika Anda mencari kata 10letter yang diawali dengan A dan diakhiri dengan B maka jika Anda menemukan posisi A dan karakter 9 lebih jauh bukanlah B maka Anda dapat melewati beberapa. lihat algoritma Knuth – Morris – Pratt



5

RegEx secara komparatif lebih cepat daripada kode yang mungkin Anda tulis karena sebagian besar pustaka adalah hasil dari banyak pengembang menghabiskan bertahun-tahun mengoptimalkannya untuk mencicit setiap bit terakhir dari kinerja yang mungkin. Sulit bagi satu orang untuk menggandakannya dalam kode pencarian mereka sendiri.


4
s / mencicit / memeras /?
Péter Török

4

Premis dasar Anda salah.

Ekspresi reguler tidak selalu lebih cepat daripada pencarian sederhana. Itu semua tergantung konteks. Itu tergantung pada kompleksitas ekspresi, panjang dokumen yang dicari, dan sejumlah faktor.

Yang terjadi adalah bahwa ekspresi reguler akan dikompilasi menjadi pengurai sederhana (yang membutuhkan waktu). Jadi, jika dokumennya kecil, waktu tambahan ini akan lebih besar daripada keuntungannya. Juga, jika ekspresinya sederhana, maka ekspresi reguler tidak akan memberi Anda keuntungan apa pun.

Jika ekspresinya kompleks dan dokumennya cukup besar, maka Anda dapat memperoleh manfaat. Apakah ini cukup signifikan untuk mempertimbangkan ekspresi reguler menjadi lebih cepat akan sangat tergantung pada seberapa banyak upaya yang ingin Anda lakukan dalam pencarian (juga ekspresi reguler mungkin memiliki beberapa optimasi yang dapat disediakan oleh perpustakaan yang Anda tidak akan memikirkan diri sendiri).

Yang ingin saya katakan adalah bahwa tidak ada jawaban menyeluruh yang menyeluruh. Jika Anda memiliki ekspresi tertentu (dan ukuran dokumen yang diketahui), maka Anda bisa mengatakan memperoleh jawaban ya / tidak untuk apakah ekspresi itu lebih cepat daripada pencarian sederhana (dan mengapa).

Keuntungan nyata dari ekspresi reguler adalah setelah Anda memahami cara menulisnya, kemampuan untuk mengekspresikan pencarian yang kompleks dengan cara yang ringkas. Karena ini adalah formulir yang digeneralisasi, Anda kemudian dapat membangun alat yang memungkinkan pencarian dengan cara yang berguna dalam kasus umum; biasanya paling tidak secepat pencarian sederhana (pada dokumen dengan ukuran minimum; pada dokumen yang lebih kecil dari ini tidak masalah karena meskipun lebih lambat, masih cukup cepat).


1

Masuk akal bahwa dalam beberapa bahasa tingkat tinggi (mungkin javascript), menggunakan pustaka regex yang diimplementasikan dalam bahasa tingkat rendah (mungkin C) akan lebih cepat daripada menulis logika parser dalam bahasa tingkat tinggi.

Masuk akal - Saya tidak tahu apakah ini benar-benar terjadi.


Yang bagus! Itu adalah sesuatu yang saya juga pertimbangkan. Tetapi dengan prosesor hari ini jauh lebih cepat dari pendahulunya, saya dapat dengan aman mengatakan jika Anda menulis kode secara efisien, Anda jarang akan dapat membedakannya. Saya sebenarnya secara keseluruhan tidak benar-benar gaga atas seluruh hipotesis reguler ekspresi lebih cepat! ;-)
user3833732
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.