Mengapa ekspresi reguler begitu kontroversial? [Tutup]

212

Ketika menjelajahi ekspresi reguler (atau dikenal sebagai RegEx-es), ada banyak individu yang tampaknya melihat ekspresi reguler sebagai Cawan Suci. Sesuatu yang terlihat sangat rumit - harus menjadi jawaban untuk setiap pertanyaan. Mereka cenderung berpikir bahwa setiap masalah dapat diselesaikan dengan menggunakan ekspresi reguler.

Di sisi lain, ada juga banyak orang yang mencoba menghindari ekspresi reguler dengan cara apa pun. Mereka mencoba mencari jalan keluar di sekitar ekspresi reguler dan menerima pengkodean tambahan hanya untuk kepentingan itu, bahkan jika ekspresi reguler akan menjadi solusi yang lebih kompak.

Mengapa ekspresi reguler dianggap sangat kontroversial? Apakah ada kesalahpahaman yang tersebar luas tentang cara kerjanya? Atau mungkinkah keyakinan luas bahwa ekspresi reguler pada umumnya lambat?

Gumbo
sumber
9
jika ini diskusi, bukankah seharusnya ditutup? tetapi saya melihat pertanyaan nyata di sana jadi mungkin tag diskusi bukan milik?
RCIX
6
Tidak bercanda. Anda mengungkitnya dan orang-orang mulai menjadi gila di sini.
Ryan Florence
1
Pengamatan yang bagus dan kata-kata dalam pertanyaan!
imz - Ivan Zakharyaschev
Pertanyaannya adalah opini berdasarkan aturan harus berlaku di sini juga (atau pertanyaan harus diedit untuk menargetkan jawaban yang tepat). Yang mengatakan saya kira regex controverse berasal dari ketidaktepatan tutorial dan manual tentang hal itu. Sebagian besar waktu jika tidak semua informasi waktu dicampur dan kita tidak diberikan semua karakteristik. Tambahkan ke bahasa yang tidak digunakan, Anda akhirnya belajar sesuatu untuk mengetahui bahwa itu mungkin berarti sesuatu yang lain. Dan akhirnya karakter regex khusus tidak terbatas pada satu makna yang menambah kebingungan.
intika

Jawaban:

136

Saya tidak berpikir orang keberatan dengan ekspresi reguler karena mereka lambat, tetapi lebih karena mereka sulit dibaca dan ditulis, dan juga sulit untuk diperbaiki. Meskipun ada beberapa situasi di mana ekspresi reguler memberikan solusi yang efektif dan ringkas untuk masalah tersebut, terkadang ekspresi tersebut disuntikkan ke dalam situasi di mana lebih baik menggunakan bagian kode yang mudah dibaca dan dikelola.

Kyle Cronin
sumber
2
Dan ya, regex bisa sangat lambat dibandingkan dengan menggunakan fungsi sederhana. Dan tidak hanya lambat, tetapi kinerja mesin regex dapat benar - benar tidak dapat diprediksi ketika dihadapkan dengan input sewenang-wenang (yang disediakan pengguna).
Pacerier
1
Jika Anda tahu cara kerja regex, itu tidak masalah sama sekali.
Shiplu Mokaddim
8
@pacerier, ini bukan pola yang lambat , ini mesin yang lambat . Kebanyakan mesin ekspresi reguler (modern) tidak cocok untuk pola yang kompleks (misalnya banyak |atau .*), karena mereka menggunakan mesin stack dan backtracking. Itu sebabnya Anda harus hati-hati menyetel ekspresi reguler Anda di Perl, Java, Python, Ruby ... Mesin ekspresi reguler gaya lama ( grepmisalnya, dalam kompilasi) mengkompilasi pola menjadi DFA. Setelah itu, kompleksitas pola sebagian besar tidak relevan. Saya hanya menggunakan Java dan grep untuk teks dan pola yang sama: 22 menit vs 2s. Inilah sainsnya: swtch.com/~rsc/regexp/regexp1.html
hagello
122

Membuat Regex Dapat Dipertahankan

Kemajuan besar menuju demistifikasi pola yang sebelumnya disebut sebagai "ekspresi reguler" adalah /xbendera regex Perl - terkadang ditulis (?x)ketika disematkan - yang memungkinkan spasi putih (pemutusan baris, indentasi) dan komentar. Ini secara serius meningkatkan keterbacaan dan karenanya pemeliharaan. Ruang putih memungkinkan untuk chunking kognitif, sehingga Anda dapat melihat kelompok apa dengan apa.

Pola-pola modern sekarang juga mendukung referensi yang relatif bernomor dan dinamai sekarang. Itu berarti Anda tidak lagi perlu menghitung kelompok tangkap untuk mengetahui bahwa Anda membutuhkan $4atau \7. Ini membantu saat membuat pola yang dapat dimasukkan dalam pola selanjutnya.

Ini adalah contoh kelompok penangkapan yang relatif bernomor:

$ dupword = qr {\ b (?: (\ w +) (?: \ s + \ g {-1}) +) \ b} xi;
$ dikutip = qr {(["']) $ dupword \ 1} x;

Dan di sini adalah contoh dari pendekatan superior dari tangkapan bernama:

$dupword = qr{ \b (?: (?<word> \w+ ) (?: \s+ \k<word> )+ ) \b }xi;
$quoted  = qr{ (?<quote> ["'] ) $dupword  \g{quote} }x;

Regex Tata Bahasa

Yang terbaik dari semuanya , tangkapan yang dinamai ini dapat ditempatkan di dalam satu (?(DEFINE)...)blok, sehingga Anda dapat memisahkan deklarasi dari eksekusi elemen-elemen yang disebut individual dari pola Anda. Ini membuat mereka bertindak seperti subrutin dalam pola.
Contoh yang bagus dari "regex gramatikal" semacam ini dapat ditemukan dalam jawaban ini dan yang ini . Ini lebih mirip deklarasi gramatikal.

Saat yang terakhir mengingatkan Anda:

... pastikan untuk tidak menulis pola derau baris. Anda tidak harus, dan Anda seharusnya tidak. Tidak ada bahasa pemrograman yang dapat dipertahankan yang melarang ruang putih, komentar, subrutin, atau pengidentifikasi alfanumerik. Jadi gunakan semua hal itu dalam pola Anda.

Ini tidak bisa terlalu ditekankan. Tentu saja jika Anda tidak menggunakan hal-hal itu dalam pola Anda, Anda akan sering membuat mimpi buruk. Tapi jika Anda lakukan menggunakan mereka, meskipun, Anda tidak perlu.

Berikut adalah contoh lain dari pola tata bahasa modern, yang ini untuk parsing RFC 5322: gunakan 5.10.0;

$rfc5322 = qr{

   (?(DEFINE)

     (?<address>         (?&mailbox) | (?&group))
     (?<mailbox>         (?&name_addr) | (?&addr_spec))
     (?<name_addr>       (?&display_name)? (?&angle_addr))
     (?<angle_addr>      (?&CFWS)? < (?&addr_spec) > (?&CFWS)?)
     (?<group>           (?&display_name) : (?:(?&mailbox_list) | (?&CFWS))? ; (?&CFWS)?)
     (?<display_name>    (?&phrase))
     (?<mailbox_list>    (?&mailbox) (?: , (?&mailbox))*)

     (?<addr_spec>       (?&local_part) \@ (?&domain))
     (?<local_part>      (?&dot_atom) | (?&quoted_string))
     (?<domain>          (?&dot_atom) | (?&domain_literal))
     (?<domain_literal>  (?&CFWS)? \[ (?: (?&FWS)? (?&dcontent))* (?&FWS)?
                                   \] (?&CFWS)?)
     (?<dcontent>        (?&dtext) | (?&quoted_pair))
     (?<dtext>           (?&NO_WS_CTL) | [\x21-\x5a\x5e-\x7e])

     (?<atext>           (?&ALPHA) | (?&DIGIT) | [!#\$%&'*+-/=?^_`{|}~])
     (?<atom>            (?&CFWS)? (?&atext)+ (?&CFWS)?)
     (?<dot_atom>        (?&CFWS)? (?&dot_atom_text) (?&CFWS)?)
     (?<dot_atom_text>   (?&atext)+ (?: \. (?&atext)+)*)

     (?<text>            [\x01-\x09\x0b\x0c\x0e-\x7f])
     (?<quoted_pair>     \\ (?&text))

     (?<qtext>           (?&NO_WS_CTL) | [\x21\x23-\x5b\x5d-\x7e])
     (?<qcontent>        (?&qtext) | (?&quoted_pair))
     (?<quoted_string>   (?&CFWS)? (?&DQUOTE) (?:(?&FWS)? (?&qcontent))*
                          (?&FWS)? (?&DQUOTE) (?&CFWS)?)

     (?<word>            (?&atom) | (?&quoted_string))
     (?<phrase>          (?&word)+)

     # Folding white space
     (?<FWS>             (?: (?&WSP)* (?&CRLF))? (?&WSP)+)
     (?<ctext>           (?&NO_WS_CTL) | [\x21-\x27\x2a-\x5b\x5d-\x7e])
     (?<ccontent>        (?&ctext) | (?&quoted_pair) | (?&comment))
     (?<comment>         \( (?: (?&FWS)? (?&ccontent))* (?&FWS)? \) )
     (?<CFWS>            (?: (?&FWS)? (?&comment))*
                         (?: (?:(?&FWS)? (?&comment)) | (?&FWS)))

     # No whitespace control
     (?<NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f])

     (?<ALPHA>           [A-Za-z])
     (?<DIGIT>           [0-9])
     (?<CRLF>            \x0d \x0a)
     (?<DQUOTE>          ")
     (?<WSP>             [\x20\x09])
   )

   (?&address)

}x;

Bukankah itu luar biasa - dan indah? Anda dapat menggunakan tata bahasa gaya BNF dan menerjemahkannya langsung ke dalam kode tanpa kehilangan struktur dasarnya!

Jika pola tata bahasa modern masih belum cukup bagi Anda, maka modul brilian Damian ConwayRegexp::Grammars menawarkan sintaks yang lebih bersih, dengan debugging yang unggul juga. Berikut kode yang sama untuk mem-parsing RFC 5322 menyusun kembali ke dalam pola dari modul itu:

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;
use Data::Dumper "Dumper";

my $rfc5322 = do {
    use Regexp::Grammars;    # ...the magic is lexically scoped
    qr{

    # Keep the big stick handy, just in case...
    # <debug:on>

    # Match this...
    <address>

    # As defined by these...
    <token: address>         <mailbox> | <group>
    <token: mailbox>         <name_addr> | <addr_spec>
    <token: name_addr>       <display_name>? <angle_addr>
    <token: angle_addr>      <CFWS>? \< <addr_spec> \> <CFWS>?
    <token: group>           <display_name> : (?:<mailbox_list> | <CFWS>)? ; <CFWS>?
    <token: display_name>    <phrase>
    <token: mailbox_list>    <[mailbox]> ** (,)

    <token: addr_spec>       <local_part> \@ <domain>
    <token: local_part>      <dot_atom> | <quoted_string>
    <token: domain>          <dot_atom> | <domain_literal>
    <token: domain_literal>  <CFWS>? \[ (?: <FWS>? <[dcontent]>)* <FWS>?

    <token: dcontent>        <dtext> | <quoted_pair>
    <token: dtext>           <.NO_WS_CTL> | [\x21-\x5a\x5e-\x7e]

    <token: atext>           <.ALPHA> | <.DIGIT> | [!#\$%&'*+-/=?^_`{|}~]
    <token: atom>            <.CFWS>? <.atext>+ <.CFWS>?
    <token: dot_atom>        <.CFWS>? <.dot_atom_text> <.CFWS>?
    <token: dot_atom>        <.CFWS>? <.dot_atom_text> <.CFWS>?
    <token: dot_atom_text>   <.atext>+ (?: \. <.atext>+)*

    <token: text>            [\x01-\x09\x0b\x0c\x0e-\x7f]
    <token: quoted_pair>     \\ <.text>

    <token: qtext>           <.NO_WS_CTL> | [\x21\x23-\x5b\x5d-\x7e]
    <token: qcontent>        <.qtext> | <.quoted_pair>
    <token: quoted_string>   <.CFWS>? <.DQUOTE> (?:<.FWS>? <.qcontent>)*
                             <.FWS>? <.DQUOTE> <.CFWS>?

    <token: word>            <.atom> | <.quoted_string>
    <token: phrase>          <.word>+

    # Folding white space
    <token: FWS>             (?: <.WSP>* <.CRLF>)? <.WSP>+
    <token: ctext>           <.NO_WS_CTL> | [\x21-\x27\x2a-\x5b\x5d-\x7e]
    <token: ccontent>        <.ctext> | <.quoted_pair> | <.comment>
    <token: comment>         \( (?: <.FWS>? <.ccontent>)* <.FWS>? \)
    <token: CFWS>            (?: <.FWS>? <.comment>)*
                             (?: (?:<.FWS>? <.comment>) | <.FWS>)

    # No whitespace control
    <token: NO_WS_CTL>       [\x01-\x08\x0b\x0c\x0e-\x1f\x7f]

    <token: ALPHA>           [A-Za-z]
    <token: DIGIT>           [0-9]
    <token: CRLF>            \x0d \x0a
    <token: DQUOTE>          "
    <token: WSP>             [\x20\x09]

    }x;

};


while (my $input = <>) {
    if ($input =~ $rfc5322) {
        say Dumper \%/;       # ...the parse tree of any successful match
                              # appears in this punctuation variable
    }
}

Ada banyak hal yang baik di dalam perlre manualnya , tapi ini perbaikan dramatis dalam fitur desain regex mendasar adalah tidak berarti terbatas pada Perl saja. Memang yang pcrepattern manualnya mungkin menjadi membaca lebih mudah, dan mencakup wilayah yang sama.

Pola modern hampir tidak memiliki kesamaan dengan hal-hal primitif yang Anda ajarkan di kelas automata terbatas Anda.

tchrist
sumber
9
IYA! IYA! Akhirnya, seseorang menunjukkan contoh yang bagus tentang bagaimana regex dapat dibaca dengan pengubah x. Saya tidak percaya betapa sedikit orang yang tahu bahwa itu ada, apalagi benar-benar menggunakannya.
Shabbyrobe
1
@ Shabbyrobe: Ini tidak adil /x. Ini menggunakan (?&name)regex secara tata bahasa, dengan subrutin regex internal, yang benar-benar membuat ini bersinar.
tchrist
+1 Anda selalu mempelajari sesuatu yang baru. Saya tidak tahu bahwa PCRE memiliki kondisi "salah" untuk didefinisikan.
NikiC
5
Python juga memiliki re.VERBOSEbendera.
Siput mekanik
3
Gunna lanjut saja dan katakan bahwa saya masih kagum pada panjang bahwa orang akan pergi untuk membuat regex dapat digunakan.
Slater Victoroff
68

Regex adalah alat yang hebat, tetapi orang-orang berpikir, "Hei, alat yang hebat, saya akan menggunakannya untuk melakukan X!" di mana X adalah sesuatu yang lebih baik untuk alat yang berbeda (biasanya parser). Ini adalah standar menggunakan palu di mana Anda memerlukan masalah obeng.

Chas. Owens
sumber
4
Hanya ingat bahwa sebagian besar pengurai - penganalisis fleksibel - masih menggunakan ekspresi reguler untuk mengurai barang-barang mereka :-)
Jasper Bekkers
62
Mengatakan bahwa parser menggunakan ekspresi reguler seperti mengatakan parser menggunakan pernyataan penugasan. Tidak ada artinya sampai Anda melihat bagaimana mereka digunakan.
Chas. Owens
24
Menggunakan RegEx ketika parser lebih baik mengganggu. Menggunakan RegEx ketika string standar bahasa menemukan atau mengganti fungsi akan bekerja (dan biasanya dalam waktu linier) tidak dapat dimaafkan.
jmucchiello
1
Setuju, karena RegEx harus menjadi jack dari semua perdagangan yang memproses biaya overhead sangat besar. Hanya karena menggunakan mesin RegEx tampaknya mudah bukan berarti itu solusi yang lebih baik daripada parser iteratif (ambang ketergantungan pengembang). Salah satu contoh favorit saya PHP split($pattern,$string)vs explode($delimiter,$string)- untungnya yang pertama semakin terdepresiasi, tetapi banyak kode menggunakan yang pertama ketika mereka hanya membutuhkan kekuatan nanti. Aggreed, RegEx's menyediakan alat yang mudah untuk melakukan beberapa hal tetapi kecuali jika Anda membutuhkan kekuatan penuh dari ekspresi reguler mereka
Rudu
4
Analisis leksikal memang dapat menggunakan regex. Mereka juga dikenal sebagai tokenizer, tetapi mereka bukan penganalisis sintaksis (atau pengurai). Untuk membaca string yang cukup rumit, tokenizer harus digunakan untuk membaca string sebagai token (mungkin dengan regex, mungkin tidak, tergantung pada tokenizer). Token ini kemudian harus diteruskan ke parser, yang akan memprosesnya dengan aturan tata bahasa, yang jelas bukan regex.
Axel
53

Hampir semua orang yang saya kenal yang menggunakan ekspresi reguler secara teratur (pun intended) berasal dari latar belakang Unix-ish di mana mereka menggunakan alat yang memperlakukan RE sebagai konstruksi pemrograman kelas satu, seperti grep, sed, awk, dan Perl. Karena hampir tidak ada overhead sintaksis untuk menggunakan ekspresi reguler, produktivitasnya naik ketika mereka melakukannya.

Sebaliknya, programmer yang menggunakan bahasa di mana RE adalah perpustakaan eksternal cenderung tidak mempertimbangkan ekspresi reguler apa yang dapat dibawa ke meja. Programmer "waktu-biaya" sangat tinggi sehingga a) RE tidak pernah muncul sebagai bagian dari pelatihan mereka, atau b) mereka tidak "berpikir" dalam hal RE dan memilih untuk kembali ke pola yang lebih akrab.

Barry Brown
sumber
11
Ya, saya tidak pernah memaafkan Python untuk membuat sintaks regex verbose dengan menggunakan perpustakaan. Saya pikir itu murni dari kewarasan.
suka
7
Saya berasal dari latar belakang unix, menggunakan sed, awk & perl memuat, dan tentu saja melakukan banyak grepping, tetapi tahu bahwa ketika saya menggunakan regex, itu adalah hack hanya-tulis yang saya benci mempertahankannya. Ini bagus untuk skrip shell / one-timer, tapi untuk pekerjaan nyata, untuk apa pun yang bukan hanya ambil-beberapa-data-untuk-menyelamatkan-sekarang, saya sekarang menggunakan tokenizer / lexer / parser yang tepat dengan sintaks yang jelas. Favorit saya melakukan semuanya, bersih + dapat mengoptimalkan diri. Saya telah belajar dengan cara yang sulit, dan selama bertahun-tahun, bahwa sedikit disiplin diri pada awalnya berarti lebih sedikit usaha di kemudian hari. Regex adalah momen di keyboard, dan seumur hidup di kerutan.
AndrewC
44

Ekspresi reguler memungkinkan Anda untuk menulis mesin finite-state custom (FSM) kustom dengan cara yang ringkas, untuk memproses serangkaian input. Setidaknya ada dua alasan mengapa menggunakan ekspresi reguler itu sulit:

  • Pengembangan perangkat lunak lama melibatkan banyak perencanaan, model kertas, dan pemikiran yang cermat. Ekspresi reguler cocok dengan model ini dengan sangat baik, karena menulis ekspresi efektif dengan benar melibatkan banyak menatapnya, memvisualisasikan jalur FSM.

    Pengembang perangkat lunak modern lebih suka mengeluarkan kode, dan menggunakan debugger untuk melakukan eksekusi, untuk melihat apakah kode itu benar. Ekspresi reguler tidak mendukung gaya kerja ini dengan baik. Satu "pelarian" dari ekspresi reguler secara efektif adalah operasi atom. Sulit untuk mengamati eksekusi bertahap di debugger.

  • Terlalu mudah untuk menulis ekspresi reguler yang secara tidak sengaja menerima lebih banyak input daripada yang Anda inginkan. Nilai ekspresi reguler tidak benar-benar cocok dengan input yang valid, itu gagal mencocokkan input yang tidak valid . Teknik untuk melakukan "tes negatif" untuk ekspresi reguler tidak terlalu canggih, atau setidaknya tidak banyak digunakan.

    Ini membuat ekspresi reguler sulit dibaca. Hanya dengan melihat ekspresi reguler, dibutuhkan banyak konsentrasi untuk memvisualisasikan semua input yang mungkin harus ditolak, tetapi diterima secara keliru. Pernah mencoba men-debug kode ekspresi reguler orang lain ?

Jika ada penolakan untuk menggunakan ekspresi reguler di antara pengembang perangkat lunak hari ini, saya pikir itu terutama karena kedua faktor ini.

Bill Karwin
sumber
4
Ada alat yang sangat baik di luar sana untuk men-debug regexps: regexbuddy.com
Jasper Bekkers
15
perl -Mre = debug -e "q [aabbcc] = ~ / ab * [cd] /"
Brad Gilbert
15
Kurasa aku tidak akan pernah bisa melihat akronim "FSM" tanpa memikirkan Flying Spaghetti Monster.
Shabbyrobe
4
@ Shabbyrobe: Saya tidak bermaksud menyinggung. Jika mau, Anda dapat menggunakan deterministic finite automaton (DFA).
Bill Karwin
37

Orang cenderung menganggap ekspresi reguler itu sulit; tapi itu karena mereka salah menggunakannya. Menulis satu kalimat yang rumit tanpa komentar, indentasi atau tangkapan bernama. (Anda tidak menjejalkan ekspresi SQL kompleks Anda dalam satu baris, tanpa komentar, indentasi atau alias, kan?). Jadi ya, bagi banyak orang, itu tidak masuk akal.

Namun, jika pekerjaan Anda ada hubungannya dengan parsing teks (kira-kira semua aplikasi web di luar sana ...) dan Anda tidak tahu ekspresi reguler, Anda payah pada pekerjaan Anda dan Anda membuang-buang waktu Anda sendiri dan bahwa Anda majikan. Ada sumber daya yang sangat bagus di luar sana untuk mengajari Anda segala sesuatu tentang mereka yang perlu Anda ketahui, dan banyak lagi.

Jasper Bekkers
sumber
2
Well .. perbedaannya adalah bahwa beberapa ruang memiliki makna dalam regex, di mana dalam bahasa lain mereka tidak dan bahwa ini mengapa mereka biasanya satu liners (yang kadang-kadang membungkus untuk beberapa baris :)
Rado
14
@Ado: Perl, misalnya, memiliki xpengubah untuk regex yang menyebabkan spasi kosong diabaikan. Ini memungkinkan Anda untuk meletakkan regex pada beberapa baris dan menambahkan komentar.
Nathan Fellman
9
Python juga memiliki re.Xalias re.VERBOSE.
Craig McQueen
2
Demikian juga xmodifikator di tcl. Saya percaya ini cukup standar karena tcl, tidak seperti bahasa lain, tidak menggunakan PCRE.
Slebetman
2
@AndrewC Itu adalah salah satu interpretasi paling buruk dari posting ini.
Jasper Bekkers
28

Karena mereka tidak memiliki alat belajar paling populer di IDE yang diterima secara umum: Tidak ada Regex Wizard. Bahkan Pelengkapan Otomatis. Anda harus mengkodekan semuanya sendirian.

dkretz
sumber
3
Maka Anda menggunakan IDE yang salah ... Bahkan editor teks saya memberikan petunjuk regex.
CurtainDog
1
Sebagai tambahan, Expresso dan The Regex Coach adalah alat yang sangat berguna untuk membangun ekspresi reguler.
Mun
22
Bagaimana mungkin Anda melengkapi ekspresi reguler secara otomatis?
AmbroseChapel
3
EditPad Pro memiliki sintaks yang disorot untuk regex di kotak pencarian, tapi saya merasa lebih mengganggu daripada membantu, dan tetap dimatikan. Tapi saya sangat menghargainya karena memberi tahu saya bahwa saya memiliki tanda kurung yang tidak cocok; kurung khususnya bisa menjadi beruang untuk melacak.
Alan Moore
2
@ AmbroseChapel - Saya terlambat beberapa tahun untuk diskusi ini. Tapi saya membuat mekanisme pelengkapan otomatis di regexhero.net/tester Ini diprakarsai oleh konstruksi umum di dalam kurung bulat (), persegi [], atau keriting {}. Ini juga akan bekerja dengan backslash.
Steve Wortham
16

Saya tidak berpikir mereka begitu kontroversial.

Saya juga berpikir Anda sudah semacam menjawab pertanyaan Anda sendiri, karena Anda menunjukkan betapa konyolnya menggunakannya di mana-mana ( Tidak semuanya adalah bahasa biasa 2 ) atau untuk tidak menggunakannya sama sekali. Anda, sang programmer, harus membuat keputusan yang cerdas tentang kapan ekspresi reguler akan membantu kode atau merusaknya. Ketika dihadapkan dengan keputusan seperti itu, dua hal penting yang perlu diingat adalah rawatan (yang menyiratkan keterbacaan) dan ekstensibilitas.

Bagi mereka yang sangat menentang mereka, tebakan saya adalah bahwa mereka tidak pernah belajar menggunakannya dengan benar. Saya pikir kebanyakan orang yang menghabiskan hanya beberapa jam dengan tutorial yang layak akan mencari tahu mereka dan menjadi lancar dengan sangat cepat. Inilah saran saya untuk mulai dari mana:

http://docs.python.org/howto/regex

Meskipun halaman itu berbicara tentang ekspresi reguler dalam konteks Python, saya menemukan informasi ini sangat berlaku di tempat lain. Ada beberapa hal yang spesifik-Python, tapi saya yakin mereka jelas dicatat, dan mudah diingat.

kode Anda
sumber
2
Halaman tersebut tampaknya telah pindah ke docs.python.org/howto/regex
Dominic K
@ Terima kasih. Saya akan mengedit jawaban saya untuk mencerminkan.
allyourcode
11

Ekspresi reguler untuk string apa operator aritmatika untuk angka, dan saya tidak akan menganggap mereka kontroversial. Saya pikir bahkan seorang aktivis OO yang cukup militan seperti saya (yang akan cenderung memilih objek lain daripada string) akan sulit ditekan untuk menolaknya.

Peter Mortensen
sumber
7

Masalahnya adalah bahwa regex berpotensi sangat kuat sehingga Anda dapat melakukan sesuatu dengan mereka sehingga Anda harus menggunakan sesuatu yang berbeda.

Seorang programmer yang baik harus tahu di mana menggunakannya, dan di mana tidak. Contoh khas adalah parsing bahasa non-reguler (lihat Memutuskan apakah suatu bahasa biasa ).

Saya pikir Anda tidak dapat salah jika pada awalnya Anda membatasi diri pada ekspresi reguler yang sebenarnya (tanpa ekstensi). Beberapa ekstensi dapat membuat hidup Anda sedikit lebih mudah, tetapi jika Anda menemukan sesuatu yang sulit untuk diungkapkan sebagai regex nyata , ini mungkin merupakan indikasi bahwa regex bukanlah alat yang tepat.

Svante
sumber
5

Anda mungkin juga bertanya mengapa goto kontroversial.

Pada dasarnya, ketika Anda mendapatkan begitu banyak kekuatan "jelas", orang cenderung menyalahgunakan mereka untuk situasi yang bukan pilihan terbaik mereka. Jumlah orang yang meminta parse CSV atau XML atau HTML di regex, misalnya, mengejutkan saya. Ini alat yang salah untuk pekerjaan itu. Tetapi beberapa pengguna tetap bersikeras menggunakan regex.

Secara pribadi, saya mencoba untuk menemukan bahwa regex yang menggunakan sedang untuk apa yang baik untuk mereka, dan menghindarinya ketika mereka kurang optimal.

Perhatikan bahwa regex masih dapat digunakan untuk mem-parsing CSV, XML, HTML, dll. Tetapi biasanya tidak dalam satu regex.

Tanktalus
sumber
Tentu Anda dapat menguraikan salah satu format ini dalam satu regex, itulah kekuatan regex, sayang! Apakah Anda ingin melakukan itu atau tidak, adalah masalah yang sama sekali berbeda.
Jasper
4

Saya tidak berpikir "kontroversial" adalah kata yang tepat.

Tetapi saya telah melihat banyak contoh di mana orang mengatakan "apa ekspresi reguler yang perlu saya lakukan manipulasi string ini-dan-itu?" yang merupakan masalah XY.

Dengan kata lain, mereka mulai dari asumsi bahwa regex adalah apa yang mereka butuhkan, tetapi mereka akan lebih baik dengan split (), terjemahan seperti tr tr's /// di mana karakter diganti satu dengan yang lain, atau hanya sebuah indeks ().

AmbroseChapel
sumber
4

Ini adalah topik yang menarik.
Banyak penggemar regexp tampaknya membingungkan keringkasan formula dengan efisiensi.
Selain itu, regexp yang membutuhkan banyak pemikiran menghasilkan kepuasan besar bagi pengarangnya yang membuatnya langsung sah.

Tapi ... regexps sangat nyaman ketika kinerja bukan masalah dan Anda harus berurusan dengan cepat dengan output teks, misalnya di Perl. Juga, sementara kinerja adalah masalah, orang mungkin memilih untuk tidak mencoba mengalahkan perpustakaan regexp dengan menggunakan algoritma buatan sendiri yang mungkin buggy atau kurang efisien.

Selain itu ada sejumlah alasan mengapa regexps dikritik secara tidak adil, misalnya

  • regexp tidak efisien, karena membangun yang teratas tidak jelas
  • beberapa programmer "lupa" untuk mengkompilasi hanya sekali regexp untuk digunakan berkali-kali (seperti Pola statis di Jawa)
  • beberapa programmer mencoba strategi trial and error - bekerja lebih sedikit dengan regexps!
e2-e4
sumber
4

Apa yang saya pikirkan adalah Mempelajari Regex dan mempertahankan regex menjadi tidak populer, sebagian besar pengembangnya malas atau kebanyakan dari mereka bergantung pada perpustakaan eksternal untuk melakukan parsing untuk mereka ... mereka bergantung pada google untuk jawabannya dan bahkan bertanya di forum untuk kode lengkap untuk masalah mereka. Tetapi ketika datang untuk mengimplementasikan atau memodifikasi / memelihara regex mereka hanya gagal.

Ada pepatah populer "Teman jangan biarkan Teman menggunakan Regex untuk Parsing HTML"

Tetapi sejauh yang saya ketahui, saya telah membuat parser HTML lengkap menggunakan Regex dan saya menemukan diri saya bahwa regex lebih baik dalam mengurai string html baik dari segi kecepatan maupun dari segi memori (jika Anda memiliki Ide apa yang ingin Anda capai :))

Rajeev
sumber
2
Saya pikir itu tidak jujur ​​untuk menghapus sebagian besar pengembang ... sebagai malas. Saya akan mengatakan bahwa sintaksisnya sangat samar, tidak intuitif, dan penuh dengan gotcha, kepada yang tidak diinisiasi, yang mengarah pada penghalang masuk yang tinggi. Untuk alasan yang sama Perl memiliki reputasi "buruk" bagi banyak orang, tetapi juga merupakan bahasa yang sangat kuat. Ini seperti mencoba membaca ekspresi matematika sebelum Anda tahu simbolnya. Ini menakutkan, dan pengembang harus bersikap yudisial dengan waktu mereka untuk mengetahui bahwa mereka akan mendapat manfaat untuk mempelajari sintaksis itu.
Katastic Voyage
Anda akan kehilangan kasus tepi dalam HTML karena HTML bukan bahasa biasa. Anda aman jika niat Anda adalah untuk menguraikan subset HTML yang dikenal
Boyang
2

Ekspresi reguler adalah misteri serius bagi banyak orang, termasuk saya. Ini bekerja dengan baik tetapi itu seperti melihat persamaan matematika. Saya senang melaporkan bahwa seseorang akhirnya telah membuat lokasi gabungan berbagai fungsi ekspresi reguler di http://regexlib.com/ . Sekarang jika Microsoft hanya akan membuat kelas ekspresi reguler yang secara otomatis akan melakukan banyak hal umum seperti menghilangkan huruf, atau memfilter tanggal.

Al Katawazi
sumber
2
Anda tidak mengerti intinya. Gagasan regex adalah bahwa Anda menginvestasikan waktu untuk mempelajarinya dan ketika Anda selesai, Anda tidak lagi memerlukan kelas magis "baca tanggal". Sebagai gantinya, dibutuhkan sedikit usaha regex untuk mereka. Selain itu, akan sedikit usaha untuk menulis satu untuk "yyyy / mm / dd" seperti yang diperlukan untuk menulis satu untuk "mm-dd-yyyy", atau bahkan satu untuk "mm-yyyy / dd" (yang menang sering terjadi, tetapi ini adalah contoh bagaimana Anda dapat melakukan hal-hal yang kelas ajaib tidak pernah bisa ")
Jasper.
1

Saya menemukan ekspresi reguler sangat berharga pada waktu-waktu tertentu. Ketika saya perlu melakukan beberapa pencarian "fuzzy", dan mungkin menggantikan. Ketika data dapat bervariasi dan memiliki keacakan tertentu. Namun, ketika saya perlu melakukan pencarian dan penggantian sederhana, atau memeriksa string, saya tidak menggunakan ekspresi reguler. Meskipun saya tahu banyak orang yang melakukannya, mereka menggunakannya untuk semuanya. Itu adalah kontroversi.

Jika Anda ingin meletakkan paku di dinding, jangan gunakan palu. Ya, itu akan berhasil, tetapi pada saat Anda mendapatkan palu, saya bisa meletakkan 20 paku payung di dinding.

Ekspresi reguler harus digunakan untuk apa mereka dirancang, dan tidak kurang.

Brent Baisley
sumber
0

Sementara saya pikir regex adalah alat yang penting, hal yang paling menjengkelkan tentang mereka adalah bahwa ada implementasi yang berbeda. Sedikit perbedaan dalam sintaksis, pengubah, dan -terutama- "keserakahan" dapat membuat segalanya benar-benar kacau, membutuhkan trial-and-error dan terkadang menghasilkan bug yang membingungkan.

ndr
sumber
bagaimana implementasi regex berbeda dalam pendekatan mereka untuk pencocokan maksimal, hal yang saya pikir Anda sebut "keserakahan"? Apakah maksud Anda perbedaan antara semantik paling kiri-terpanjang versus paling lama-terpanjang ? Itulah satu-satunya perbedaan yang saya ketahui; yaitu, apakah keserakahan mengalahkan keinginan atau sebaliknya .
tchrist
0

Dalam beberapa kasus saya pikir Anda HARUS menggunakannya. Misalnya untuk membangun lexer.

Menurut pendapat saya, ini adalah sudut pandang orang yang dapat menulis regexp dan orang yang tidak (atau sulit). Saya kira ini adalah pemikiran yang bagus misalnya untuk memvalidasi input formulir, baik itu dalam javascript untuk memperingatkan pengguna, atau dalam bahasa sisi server.

Aif
sumber
0

Saya pikir ini adalah teknik yang kurang dikenal di kalangan programmer. Jadi, tidak ada penerimaan yang luas untuk itu. Dan jika Anda memiliki manajer non-teknis untuk meninjau kode Anda atau meninjau pekerjaan Anda maka ekspresi reguler sangat buruk. Anda akan menghabiskan berjam-jam menulis ekspresi reguler yang sempurna, dan Anda akan mendapatkan beberapa nilai untuk modul karena dia telah menulis begitu sedikit baris kode. Juga, seperti yang dikatakan di tempat lain, membaca ekspresi reguler adalah tugas yang sangat sulit.

Satya Prakash
sumber
1
Membaca ekspresi reguler adalah tugas yang sulit hanya ketika programmer yang membuatnya gagal menggunakan spasi putih, komentar, pengidentifikasi alfanumerik, dan mungkin juga menanamkan subrutin melalui eksekusi tertunda. Singkatnya, semua teknik rekayasa perangkat lunak yang berlaku untuk pemrograman umum juga harus diikuti dalam ekspresi reguler. Jika prinsip-prinsip ini diabaikan, maka penulis tidak menghasilkan kode profesional.
tchrist
Saya pikir manajer Anda tidak tahu bahwa "Pahlawan pemrograman sebenarnya adalah orang yang menulis kode negatif."
Rajeev
Jika manajer Anda akan memberi tahu Anda untuk menyelesaikan pekerjaan dengan 3 baris kode (termasuk regexps), sambil memuji beberapa rekan kerja doofus yang melakukannya di 900 baris Assembler ... Saya sarankan mencari pekerjaan baru.
Phil Perry
0

Sistem ekspresi reguler yang layak seperti yang digunakan dalam lex dan yacc untuk definisi kompiler bagus, sangat berguna dan bersih. Dalam sistem ini, tipe ekspresi didefinisikan dalam istilah orang lain. Ekspresi reguler satu-liner garis-derau malformasi mengerikan yang tidak terbaca yang biasa ditemukan dalam kode perl dan sed (dll) yang 'kontroversial' (sampah).

Sam Watkins
sumber
-4

Penggunaan regex terbaik yang valid dan normal adalah untuk validasi format alamat email.

Itu aplikasi yang bagus.

Saya telah menggunakan ekspresi reguler berulang kali sebagai one-off di TextPad untuk memijat file datar, membuat file csv, membuat pernyataan penyisipan SQL dan hal-hal semacam itu.

Ekspresi reguler yang ditulis dengan baik tidak boleh terlalu lambat. Biasanya alternatif, seperti banyak panggilan untuk Ganti adalah opsi yang jauh lebih lambat. Mungkin juga melakukannya dalam satu pass.

Banyak situasi membutuhkan ekspresi yang tepat dan tidak ada yang lain.

Mengganti karakter non-cetak khusus dengan karakter tidak berbahaya adalah penggunaan lain yang baik.

Tentu saja saya bisa membayangkan bahwa ada beberapa basis kode yang terlalu sering menggunakan ekspresi reguler sehingga merugikan pemeliharaan. Saya belum pernah melihat itu sendiri. Saya sebenarnya telah dihalangi oleh pengulas kode karena tidak cukup menggunakan ekspresi reguler.

Chris Morley
sumber
10
Pengalaman menunjukkan bahwa regex sebenarnya adalah alat yang sangat buruk untuk validasi format alamat email. Validator format yang benar-benar lengkap diimplementasikan sebagai sebuah regex adalah monstrositas multi-ratus karakter, sementara sebagian besar validator "cukup baik" pendek yang kebanyakan orang ambil 5 menit untuk membuat akan menolak kategori besar alamat yang valid dan dapat dikirim.
Dave Sherohman
Aku dengar, Bung. Saya sedang berbicara tentang "cukup baik" dan sementara petak besar mungkin besar dalam teori, pertimbangkan persentase cakupan yang Anda dapatkan dalam ekspresi yang begitu singkat. Saya juga telah melihat keburukan itu, tetapi apa alternatif elegan Anda?
Chris Morley
2
Saya telah menggunakan sesuatu seperti \ w @ \ w +. \ W + untuk menemukan alamat email dengan cepat di direktori besar file di mana kecepatan penting dan beberapa positif palsu atau negatif palsu tidak penting. Tetapi cara terbaik untuk memvalidasi alamat email adalah mengirim email ke alamat itu.
RossFabricant
Ya email spesifikasi alamat adalah berantakan stackoverflow.com/questions/611775/...
Nick Van Brunt
@Nick, @Dave: Validasi alamat email tidak perlu berantakan.
tchrist