Apa yang dimaksud dengan "Sekarang Anda memiliki dua masalah"?

200

Ada kutipan populer oleh Jamie Zawinski :

Beberapa orang, ketika dihadapkan dengan masalah, berpikir, "Saya tahu, saya akan menggunakan ekspresi reguler." Sekarang mereka memiliki dua masalah.

Bagaimana kutipan ini dipahami?

IQAndreas
sumber
46
Masalah ke-2 adalah mereka menggunakan regex dan masih belum menyelesaikan masalah pertama, maka 2 masalah.
Ampt
24
@Euphoric - sebenarnya, kode yang baik adalah pendek - tapi tanpa samar ringkas.
Steve314
24
@IQAndreas: Saya pikir ini dimaksudkan untuk semi-humor. Komentar yang dibuat adalah bahwa jika Anda tidak berhati-hati, menggunakan ekspresi reguler dapat memperburuk keadaan dan bukannya menjadi lebih baik.
FrustratedWithFormsDesigner
145
Beberapa orang, ketika mencoba menjelaskan sesuatu, berpikir, "Saya tahu, saya akan menggunakan kutipan Jamie Zawinski." Sekarang mereka memiliki dua hal untuk dijelaskan.
Detly

Jawaban:

220

Beberapa teknologi pemrograman pada umumnya tidak dipahami dengan baik oleh programmer ( ekspresi reguler , floating point , Perl , AWK , IoC ... dan lainnya ).

Ini bisa menjadi alat yang luar biasa kuat untuk menyelesaikan serangkaian masalah yang tepat. Ekspresi reguler khususnya sangat berguna untuk mencocokkan bahasa reguler. Dan ada inti masalahnya: hanya sedikit orang yang tahu bagaimana mendeskripsikan bahasa reguler (itu bagian dari teori ilmu komputer / linguistik yang menggunakan simbol-simbol lucu - Anda dapat membacanya di hierarki Chomsky ).

Ketika berurusan dengan hal-hal ini, jika Anda salah menggunakannya, tidak mungkin Anda benar-benar menyelesaikan masalah awal Anda. Menggunakan ekspresi reguler untuk mencocokkan HTML (kejadian yang terlalu umum) akan berarti bahwa Anda akan kehilangan case edge. Dan sekarang, Anda masih memiliki masalah asli yang tidak Anda selesaikan, dan bug halus lainnya yang muncul dengan menggunakan solusi yang salah.

Ini bukan untuk mengatakan bahwa ekspresi reguler tidak boleh digunakan, melainkan bahwa seseorang harus bekerja untuk memahami serangkaian masalah yang dapat mereka selesaikan dan tidak dapat memecahkan dan menggunakannya dengan bijaksana.

Kunci untuk memelihara perangkat lunak adalah menulis kode yang dapat dipelihara. Menggunakan ekspresi reguler dapat berlawanan dengan tujuan itu. Saat bekerja dengan ekspresi reguler, Anda telah menulis komputer mini (khususnya otomat keadaan terbatas non-deterministik ) dalam bahasa khusus domain khusus. Sangat mudah untuk menulis 'Hello world' yang setara dalam bahasa ini dan mendapatkan kepercayaan yang belum sempurna di dalamnya, tetapi melangkah lebih jauh perlu dihalangi dengan pemahaman bahasa reguler untuk menghindari penulisan bug tambahan yang bisa sangat sulit diidentifikasi dan diperbaiki (karena mereka bukan bagian dari program tempat ekspresi reguler berada).

Jadi sekarang Anda punya masalah baru; Anda memilih alat ekspresi reguler untuk menyelesaikannya (ketika tidak sesuai), dan Anda memiliki dua bug sekarang, yang keduanya lebih sulit ditemukan, karena mereka tersembunyi di lapisan abstraksi lain.

Komunitas
sumber
8
Saya tidak yakin perl itu sendiri termasuk dalam daftar teknologi yang tidak dipahami oleh programmer;)
crad
21
@crad lebih dari yang dikatakan tentang perl juga ... Banyak orang telah mendengarnya dipopulerkan di sana. Saya masih suka floating point satu di rand talk: "Sekarang Anda memiliki masalah 2.00000152"
56
@crad Beberapa orang, ketika dihadapkan dengan masalah, berpikir "Saya tahu, saya akan menggunakan perl." Sekarang mereka memiliki masalah $ (^ @ #% () ^%) (#).
Michael Hampton
4
@Jen jika ada, kekuatan tambahan dari PCRE vs regex tradisional membuatnya menjadi solusi yang lebih menggoda dan lebih sulit untuk mempertahankannya. Automata terbatas yang cocok dengan PCRE dieksplorasi dalam Memperluas Finata Automata untuk Mencocokkan Ekspresi Reguler Kompatibel Kompatibel yang Efisien ... dan itu adalah hal yang tidak sepele. Setidaknya dengan regex tradisional, seseorang dapat mengatasinya tanpa terlalu banyak kesulitan begitu konsep yang diperlukan dipahami.
6
Anda membuat poin yang bagus. ekspresi reguler secara efektif merupakan bahasa kedua, non-sepele. Bahkan jika programmer asli kompeten dalam bahasa utama dan citarasa regex yang digunakan, menambahkan dalam "bahasa kedua" berarti peluang yang lebih rendah sehingga pengelola tahu keduanya. Belum lagi bahwa keterbacaan regex sering lebih rendah dari bahasa "tuan rumah".
JS.
95

Ekspresi reguler - terutama yang tidak sepele - berpotensi sulit untuk dikodekan, dipahami, dan dipelihara. Anda hanya perlu melihat jumlah pertanyaan pada Stack Overflow yang ditandai di [regex]mana si penanya berasumsi bahwa jawaban untuk masalah mereka adalah regex dan kemudian macet. Dalam banyak kasus masalahnya dapat (dan mungkin harus) diselesaikan dengan cara yang berbeda.

Ini berarti, jika Anda memutuskan untuk menggunakan regex Anda sekarang memiliki dua masalah:

  1. Masalah asli yang ingin Anda pecahkan.
  2. Dukungan regex.

Pada dasarnya, saya pikir maksudnya Anda hanya boleh menggunakan regex jika tidak ada cara lain untuk menyelesaikan masalah Anda. Solusi lain mungkin akan lebih mudah untuk dikodekan, dirawat, dan didukung. Mungkin lebih lambat atau kurang efisien, tetapi jika itu tidak kritis, kemudahan pemeliharaan dan dukungan harus menjadi perhatian utama.

ChrisF
sumber
27
Dan lebih buruk lagi: mereka hanya cukup kuat untuk menipu orang agar mencoba menggunakannya untuk menguraikan hal-hal yang tidak dapat mereka lakukan, seperti HTML. Lihat banyak pertanyaan di SO pada "bagaimana cara menguraikan HTML?"
Frank Shearar
6
Untuk situasi tertentu regex mengagumkan. Dalam banyak kasus lain tidak begitu banyak. Di ujung lain itu adalah lubang keputusasaan yang mengerikan. Masalahnya sering muncul ketika seseorang mempelajarinya untuk pertama kali dan mulai melihat aplikasi di mana-mana. Pepatah terkenal lainnya: "Ketika satu-satunya alat yang Anda miliki adalah palu, semuanya tampak seperti paku."
Todd Williamson
3
Apakah ini berarti bahwa dengan jumlah pertanyaan dalam tag SO [c #], itu adalah bahasa pemrograman yang paling sulit untuk dipahami?
2
Saya lebih suka melihat ekspresi reguler yang kompleks daripada serangkaian panggilan untuk metode string. OTOH, saya sangat benci melihat ekspresi reguler disalahgunakan untuk menguraikan bahasa yang kompleks.
kevin cline
5
"Pada dasarnya, saya pikir maksudnya Anda hanya boleh menggunakan regex jika tidak ada cara lain untuk menyelesaikan masalah Anda. Solusi lain akan lebih mudah untuk dikodekan, dirawat, dan didukung." - sangat tidak setuju .. Regex adalah alat yang sangat baik, Anda hanya perlu tahu batasnya. Banyak tugas yang bisa dikodekan dengan lebih elegan dengan regex. (tapi, hanya untuk membuat contoh, Anda tidak boleh menggunakannya untuk mem-parsing HTML)
Karoly Horvath
69

Ini sebagian besar lelucon yang dilakukan dengan lidah, meskipun dengan kebenaran.

Ada beberapa tugas yang ekspresi regulernya sangat pas. Saya pernah mengganti 500 baris kode parser keturunan rekursif ditulis secara manual dengan satu ekspresi reguler yang memakan waktu sekitar 10 menit untuk sepenuhnya debug. Orang mengatakan regex sulit dipahami dan didebug, tetapi yang diterapkan dengan tepat hampir tidak sulit untuk didebug sebagai parser besar yang dirancang dengan tangan. Dalam contoh saya, butuh dua minggu untuk men-debug semua kasus tepi dari solusi non-regex.

Namun, untuk parafrase Paman Ben:

Dengan ekspresivitas yang luar biasa, muncul tanggung jawab yang besar.

Dengan kata lain, regex menambahkan ekspresifitas ke bahasa Anda, tetapi hal itu memberi lebih banyak tanggung jawab pada programmer untuk memilih mode ekspresi yang paling mudah dibaca untuk tugas yang diberikan.

Beberapa hal awalnya terlihat seperti tugas yang baik untuk ekspresi reguler, tetapi tidak. Misalnya, apa pun dengan token bersarang, seperti HTML. Terkadang orang menggunakan ekspresi reguler ketika metode yang lebih sederhana lebih jelas. Misalnya, string.endsWith("ing")lebih mudah dipahami daripada regex yang setara. Kadang-kadang orang mencoba menjejalkan masalah besar menjadi satu regex, di mana memecahnya menjadi lebih baik. Kadang-kadang orang gagal membuat abstraksi yang sesuai, mengulangi suatu regex berulang-ulang alih-alih menciptakan fungsi yang dinamai dengan baik untuk melakukan pekerjaan yang sama (mungkin diimplementasikan secara internal dengan sebuah regex).

Untuk beberapa alasan, regex memiliki kecenderungan aneh untuk membuat titik buta dengan prinsip-prinsip rekayasa perangkat lunak normal seperti tanggung jawab tunggal dan KERING. Itu sebabnya bahkan orang-orang yang mencintai mereka terkadang merasa bermasalah.

Karl Bielefeldt
sumber
10
Bukankah Paman Ben juga mengatakan "Hasil sempurna, setiap saat"? Mungkin itu sebabnya orang menjadi sangat senang dengan regex ...
Andrzej Doyle
4
Masalah dengan regex mengenai HTML yang menjangkiti pengembang yang tidak berpengalaman adalah bahwa HTML memiliki tata bahasa bebas konteks, tidak teratur: regex dapat digunakan untuk beberapa penguraian HTML (atau XML) sederhana (misalnya, mengambil URL dari tag jangkar bernama), tetapi tidak cocok untuk sesuatu yang kompleks. Untuk itu, penguraian DOM lebih tepat. Bacaan terkait: Hirarki Chomsky .
53

Jeff Atwood mengeluarkan interpretasi berbeda dalam posting blog yang membahas kutipan ini: Ekspresi Reguler: Sekarang Anda Punya Dua Masalah (terima kasih kepada Euphoric atas tautannya)

Menganalisa teks lengkap posting Jamie di utas asli 1997, kami menemukan yang berikut:

Sifat Perl mendorong penggunaan ekspresi reguler hampir dengan mengesampingkan semua teknik lainnya; mereka jauh dan merupakan cara yang paling "jelas" (paling tidak, bagi orang-orang yang tidak tahu lebih baik) untuk beralih dari titik A ke titik B.

Kutipan pertama terlalu glib untuk dianggap serius. Tapi ini, saya sepenuhnya setuju. Inilah intinya yang Jamie coba buat: bukan bahwa ekspresi reguler itu jahat, tapi itu terlalu sering menggunakan ekspresi reguler itu jahat.

Bahkan jika Anda benar - benar memahami ekspresi reguler, Anda mengalami masalah The Golden Hammer , mencoba menyelesaikan masalah dengan ekspresi reguler, ketika itu akan lebih mudah dan lebih jelas untuk melakukan hal yang sama dengan kode reguler (lihat juga CodingHorror: Regex use vs. penyalahgunaan Regex ).

Ada posting blog lain yang melihat konteks kutipan, dan masuk ke lebih detail daripada Atwood: Blog Jeffrey Friedl: Sumber kutipan terkenal "Sekarang Anda punya dua masalah"

IQAndreas
sumber
3
Bagi saya, inilah jawaban terbaik karena menambah konteks. Kritik jwz terhadap regex sama banyak tentang Perl seperti apa pun.
Evicatos
3
@Evicatos Bahkan ada lebih banyak penelitian yang dilakukan pada utas 1997 yang sama di posting blog lain: regex.info/blog/2006-09-15/247
IQAndreas
30

Ada beberapa hal yang terjadi dengan kutipan ini.

  1. The kutipan adalah penyajian kembali lelucon sebelumnya:

    Setiap kali menghadapi masalah, beberapa orang mengatakan "Mari kita gunakan AWK." Sekarang, mereka memiliki dua masalah. - D. Tilbrook

    Ini adalah lelucon dan penggalian nyata, tetapi juga cara menyoroti regex sebagai solusi buruk dengan menghubungkannya dengan solusi buruk lainnya. Ini adalah momen besar yang sangat serius .

  2. Bagi saya — ingatkan Anda, kutipan ini sengaja terbuka untuk interpretasi — artinya langsung ke depan. Cukup mengumumkan gagasan menggunakan ekspresi reguler belum menyelesaikan masalah. Selain itu, Anda telah meningkatkan kompleksitas kognitif kode dengan menambahkan bahasa tambahan dengan aturan yang berbeda dari bahasa apa pun yang Anda gunakan.

  3. Meskipun lucu sebagai lelucon, Anda harus membandingkan kompleksitas solusi non-regex dengan kompleksitas solusi regex + kompleksitas tambahan termasuk regex. Mungkin bermanfaat untuk menyelesaikan masalah dengan regex, meskipun ada biaya tambahan untuk menambahkan regex.

Jeffery Thomas
sumber
21

RegulerExpressionssekarangmenutuppelatihanuntukmemeliharaisetelahnyadapatterformatkeduanya; memangadapatdilakukansecara lebih baikuntukadalambeberapabarang inidalamnyapemungkinannyadimempertarakanpertanggungjawabankarenaberlakuuntukmemformatandan orang yang tidak mengetahuiatau secara langsung.

(Ekspresi Reguler tidak lebih buruk untuk dibaca atau dipelihara daripada konten yang tidak diformat lainnya; memang regex mungkin lebih mudah dibaca daripada teks ini di sini - tetapi sayangnya mereka memiliki reputasi yang buruk karena beberapa implementasi tidak memungkinkan pemformatan dan orang pada umumnya tidak tahu kamu bisa melakukannya.)


Berikut ini contoh sepele:

^(?:[^,]*+,){21}[^,]*+$


Yang sebenarnya tidak terlalu sulit untuk dibaca atau dikelola, tetapi bahkan lebih mudah ketika terlihat seperti ini:

(?x)    # enables comments, so this whole block can be used in a regex.
^       # start of string

(?:     # start non-capturing group
  [^,]*+  # as many non-commas as possible, but none required
  ,       # a comma
)       # end non-capturing group
{21}    # 21 of previous entity (i.e. the group)

[^,]*+  # as many non-commas as possible, but none required

$       # end of string

Itu sedikit contoh berlebihan (berkomentar $mirip dengan berkomentar i++) tetapi jelas tidak boleh ada masalah membaca, memahami, dan mempertahankannya.


Selama Anda jelas tentang kapan ekspresi reguler cocok dan ketika mereka ide yang buruk, tidak ada yang salah dengan mereka, dan sebagian besar kutipan JWZ tidak benar-benar berlaku.

Peter Boughton
sumber
1
Tentu, tapi saya tidak mencari diskusi tentang manfaat dari regex, dan saya tidak ingin melihat diskusi ini berjalan seperti itu. Saya hanya mencoba memahami apa yang dia maksud.
Paul Biggar
1
Kemudian tautan dalam komentar livibetter memberi tahu Anda apa yang perlu Anda ketahui. Tanggapan ini hanya menunjukkan bahwa regex tidak perlu tidak jelas, dan dengan demikian kutipannya tidak masuk akal.
Peter Boughton
8
Apa gunanya menggunakan *+? Bagaimana itu berbeda (secara fungsional) dari adil *?
Timwi
1
Meskipun apa yang Anda katakan mungkin benar, itu tidak menjawab pertanyaan khusus ini. Jawaban Anda bermuara pada "menurut pendapat saya bahwa kutipan biasanya tidak benar". Pertanyaannya bukan tentang apakah itu benar atau tidak, tetapi apa artinya kutipan itu.
Bryan Oakley
2
Tidak ada gunanya melakukan *+hal ini; semuanya berlabuh dan dapat dicocokkan dalam satu lintasan oleh otomat yang dapat menghitung hingga 22. Pengubah yang benar pada set non-koma itu baru saja tua *. (Terlebih lagi, seharusnya tidak ada perbedaan antara algoritma pencocokan serakah dan non-serakah di sini. Ini adalah kasus yang sangat sederhana.)
Donal Fellows
14

Selain jawaban ChrisF - bahwa ekspresi reguler "sulit untuk dikodekan, dipahami, dan dipertahankan", ada yang lebih buruk: mereka hanya cukup kuat untuk mengelabui orang agar mencoba menggunakannya untuk menguraikan hal-hal yang tidak dapat mereka lakukan, seperti HTML. Lihat banyak pertanyaan di SO pada "bagaimana cara menguraikan HTML?" Misalnya, satu - satunya jawaban paling epik dalam semua SO!

Frank Shearar
sumber
14

Ekspresi reguler sangat kuat, tetapi mereka memiliki satu masalah kecil dan satu besar; mereka sulit untuk ditulis, dan hampir mustahil untuk dibaca.

Dalam kasus terbaik penggunaan ekspresi reguler memecahkan masalah, jadi Anda hanya memiliki masalah pemeliharaan kode yang rumit. Jika Anda tidak mendapatkan persamaan reguler dengan benar, Anda memiliki masalah asli dan masalah dengan kode yang tidak dapat dibaca yang tidak berfungsi.

Terkadang ekspresi reguler disebut sebagai kode hanya-tulis. Dihadapkan dengan ekspresi reguler yang perlu diperbaiki, seringkali lebih cepat untuk memulai dari awal daripada mencoba memahami ekspresi.

Guffa
sumber
1
Masalah sebenarnya adalah bahwa regexps tidak dapat mengimplementasikan misal pengurai karena mereka tidak dapat menghitung seberapa dalam mereka saat ini bersarang.
4
@ Thorbjørn Ravn Andersen: Itu lebih merupakan batasan daripada masalah. Ini hanya masalah jika Anda mencoba menggunakan ekspresi reguler untuk itu, dan kemudian itu bukan masalah dengan ekspresi reguler, itu masalah dengan pilihan metode Anda.
Guffa
1
Anda dapat menggunakan REs saja untuk lexer (well, untuk sebagian besar bahasa) tetapi merakit aliran token ke pohon parse (yaitu, parsing ) secara formal di luar mereka.
Donal Fellows
10

Masalahnya adalah bahwa regex adalah binatang yang rumit, dan Anda hanya menyelesaikan masalah Anda jika Anda menggunakan regex dengan sempurna. Jika tidak, Anda memiliki 2 masalah: masalah dan regex asli Anda .

Anda mengklaim bahwa itu dapat melakukan pekerjaan seratus baris kode, tetapi Anda juga bisa membuat argumen bahwa 100 baris kode yang jelas dan ringkas lebih baik daripada satu baris regex.

Jika Anda memerlukan beberapa bukti tentang ini: Anda dapat memeriksa SO Classic ini atau hanya menyisir melalui Tag Regex SO

Ampt
sumber
8
Tak satu pun dari klaim dalam kalimat pertama Anda yang benar. Regex tidak terlalu rumit, dan tidak seperti alat lain yang Anda butuhkan untuk mengetahuinya dengan sempurna untuk menyelesaikan masalah dengannya. Itu hanya FUD. Paragraf kedua Anda benar-benar menggelikan: tentu saja Anda dapat mengajukan argumen. Tapi itu tidak bagus.
Konrad Rudolph
1
@KonradRudolph Saya pikir fakta bahwa ada banyak generasi regex dan alat validasi menunjukkan bahwa regex adalah mekanisme yang rumit. Ini tidak dapat dibaca oleh manusia (dengan desain) dan dapat menyebabkan perubahan lengkap dalam aliran untuk seseorang memodifikasi atau menulis sepotong kode yang menggunakan regex. Adapun bagian kedua, saya pikir itu jelas implikasinya dari pengelompokan luas pengetahuan tentang P.SE dan dengan mengatakan "Kode debug dua kali lebih sulit daripada menulisnya, jadi jika Anda menulis kode yang paling pintar yang Anda bisa, Anda menurut definisi, tidak cukup pintar untuk men-debug-nya "
Ampt
2
Itu bukan argumen yang tepat. Ya, tentu regex itu kompleks. Tapi begitu juga bahasa pemrograman lainnya. Regex jauh lebih kompleks daripada kebanyakan bahasa lain, dan alat yang ada untuk regex dikerdilkan oleh alat pengembangan untuk bahasa lain (FWIW saya bekerja secara luas dengan regex dan saya belum pernah menggunakan alat seperti itu ...). Ini adalah kebenaran sederhana bahwa bahkan regex kompleks lebih sederhana daripada kode parsing non-regex yang setara.
Konrad Rudolph
@KonradRudolph Saya pikir kami memiliki perbedaan pendapat mendasar tentang definisi kata sederhana. Saya akan memberi Anda bahwa regex bisa lebih efisien atau bahkan lebih kuat tetapi saya tidak berpikir bahwa sederhana adalah kata yang muncul di benak siapa pun ketika Anda memikirkan regex.
Ampt
Mungkin kita lakukan tetapi definisi saya dapat ditindaklanjuti: Saya mengambil sederhana berarti mudah dipahami, mudah dirawat, jumlah bug yang rendah disembunyikan dll. Tentu saja regex yang kompleks pada pandangan pertama tidak akan terlihat sangat mudah dipahami. Tetapi hal yang sama berlaku untuk potongan kode non-regex yang setara. Saya tidak pernah mengatakan bahwa regex itu sederhana. Saya mengatakan mereka lebih sederhana - saya membandingkan. Itu penting.
Konrad Rudolph
7

Arti memiliki dua bagian:

  • Pertama, Anda tidak menyelesaikan masalah aslinya.
    Ini mungkin merujuk pada fakta bahwa ekspresi reguler sering menawarkan solusi tidak lengkap untuk masalah umum.
  • Kedua, Anda sekarang menambahkan kesulitan tambahan yang terkait dengan solusi yang Anda pilih.
    Dalam kasus ekspresi reguler, kesulitan tambahan mungkin merujuk pada kompleksitas, pemeliharaan, atau kesulitan tambahan yang terkait dengan membuat ekspresi reguler sesuai dengan masalah yang tidak seharusnya dipecahkan.
tylerl
sumber
7

Ketika Anda memintanya pada tahun 2014, akan menarik untuk fokus pada bahasa pemrograman ideologi konteks 1997 dibandingkan dengan konteks saat ini. Saya tidak akan memasuki debat ini di sini tetapi pendapat tentang Perl dan Perl sendiri telah sangat berubah.

Namun, untuk tetap dalam konteks 2013 ( de l'eau a coulé sous les ponts depuis), saya akan menyarankan untuk fokus pada pemeragaan kembali dalam kutipan menggunakan komik XKCD terkenal yang merupakan kutipan langsung dari Jamie Zawinski :

Komik dari XKCD tentang regex, Perl dan masalah

Pertama saya memiliki masalah untuk memahami komik ini karena itu adalah referensi ke kutipan Zawinski, dan kutipan dari lirik lagu Jay-z, dan referensi dari GNU program --help -zflag 2 , jadi, terlalu banyak budaya bagi saya untuk memahaminya.

Saya tahu itu menyenangkan, saya merasakannya, tetapi saya tidak benar-benar tahu mengapa. Orang-orang sering membuat lelucon tentang Perl dan regex, terutama karena itu bukan bahasa pemrograman paling keren, tidak benar-benar tahu mengapa itu seharusnya menyenangkan ... Mungkin karena penjual Perl melakukan hal-hal konyol .

Jadi kutipan awal tampaknya menjadi lelucon sarkastik berdasarkan masalah kehidupan nyata (sakit?) Yang disebabkan oleh pemrograman dengan alat yang menyakitkan. Sama seperti palu yang bisa melukai tukang batu, pemrograman dengan alat yang bukan yang akan dipilih pengembang jika ia bisa menyakiti (otak, perasaan). Terkadang, debat hebat tentang alat mana yang paling baik terjadi, tetapi hampir tidak berharga karena itu masalah selera Anda atau selera tim pemrograman Anda , alasan budaya atau ekonomi . Komik XKCD lain yang luar biasa tentang ini:

Komik dari XKCD tentang debat alat pemrograman

Saya dapat memahami orang-orang merasa sakit dengan regex, dan mereka percaya bahwa alat lain lebih cocok untuk apa regex dirancang untuk. Ketika @ karl-bielefeldt menjawab pertanyaan Anda dengan sangat ekspresif, datang tanggung jawab besar , dan regex sangat peduli dengan hal ini. Jika pengembang tidak peduli bagaimana dia berurusan dengan regex, pada akhirnya akan menyebalkan bagi orang yang akan mempertahankan kode nanti.

Saya akan menyelesaikan dengan jawaban ini tentang pemeragaan kutipan oleh kutipan yang menunjukkan contoh khas dari Perl Best Practices karya Damian Conw ay (buku 2005).

Dia menjelaskan bahwa menulis pola seperti ini:

m{'[^\\']*(?:\\.[^\\']*)*'}

... tidak lebih dapat diterima daripada menulis program seperti ini :

sub'x{local$_=pop;sub'_{$_>=$_[0
]?$_[1]:$"}_(1,'*')._(5,'-')._(4
,'*').$/._(6,'|').($_>9?'X':$_>8
?'/':$")._(8,'|').$/._(2,'*')._(
7,'-')._(3,'*').$/}print$/x($=).
x(10)x(++$x/10).x($x%10)while<>;

Tapi itu bisa ditulis ulang , itu masih tidak cantik, tapi setidaknya sekarang bisa bertahan.

# Match a single-quoted string efficiently...
m{ '            # an opening single quote
    [^\\']*     # any non-special chars (i.e., not backslash or single quote)
    (?:         # then all of...`
    \\ .        # any explicitly backslashed char
    [^\\']*     #    followed by any non-special chars
    )*          # ...repeated zero or more times
    '           # a closing single quote
}x

Jenis kode berbentuk persegi panjang ini adalah masalah kedua bukan regex yang dapat diformat dengan cara yang jelas, dapat dipelihara dan mudah dibaca.

Smonff
sumber
2
/* Multiply the first 10 values in an array by 2. */ for (int i = 0 /* the loop counter */; i < 10 /* continue while it is less than 10 */; ++i /* and increment it by 1 in each iteration */) { array[i] *= 2; /* double the i-th element in the array */ }
5gon12eder
6

Jika ada satu hal yang harus Anda pelajari dari ilmu komputer, itu adalah hierarki Chomsky . Saya akan mengatakan bahwa semua masalah dengan ekspresi reguler berasal dari upaya untuk mengurai tata bahasa bebas konteks dengan itu. Saat Anda bisa memaksakan batas (atau berpikir Anda bisa memaksakan batas) ke level bersarang di CFG, Anda mendapatkan ekspresi reguler yang panjang dan kompleks.

Juha Autero
sumber
1
Iya! Orang-orang yang mempelajari ekspresi reguler tanpa bagian latar belakang CS tidak selalu mengerti bahwa hanya ada beberapa hal yang tidak dapat dilakukan oleh regex secara matematis .
benzado
5

Ekspresi reguler lebih cocok untuk tokenisasi daripada parsing skala penuh.

Tetapi, satu set besar hal-hal yang perlu diurai oleh programer dapat diuraikan dengan bahasa reguler (atau, lebih buruk lagi, hampir dapat diuraikan oleh bahasa biasa dan jika Anda hanya menulis sedikit kode lagi ...).

Jadi jika seseorang terbiasa dengan "aha, saya harus memilih teks terpisah, saya akan menggunakan ekspresi reguler", mudah untuk turun rute itu, ketika Anda membutuhkan sesuatu yang lebih dekat dengan otomat push-down, parser CFG atau tata bahasa bahkan lebih kuat. Itu biasanya berakhir dengan air mata.

Jadi, saya pikir kutipannya tidak terlalu membanting regexps, mereka memiliki penggunaannya (dan digunakan dengan baik, mereka memang sangat berguna), tetapi ketergantungan yang berlebihan pada regexps (atau, khususnya, pilihan tidak kritis dari mereka) .

Vatine
sumber
3

jwz hanya dari kursi goyang dengan kutipan itu. ekspresi reguler tidak berbeda dari fitur bahasa mana pun - mudah kacau, sulit digunakan dengan elegan, kuat di kali, tidak tepat di kali, sering didokumentasikan dengan baik, sering berguna.

hal yang sama dapat dikatakan untuk aritmatika floating point, penutupan, orientasi objek, I / O asinkron, atau apa pun yang Anda dapat nama. jika Anda tidak tahu apa yang Anda lakukan, bahasa pemrograman bisa membuat Anda sedih.

jika menurut Anda regex sulit dibaca, coba baca penerapan parser yang setara untuk mengonsumsi pola yang dimaksud. sering regex menang karena mereka lebih kompak daripada parser penuh ... dan dalam kebanyakan bahasa, mereka lebih cepat juga.

jangan menunda menggunakan ekspresi reguler (atau fitur bahasa lainnya) karena blogger yang mempromosikan diri membuat pernyataan yang tidak memenuhi syarat. coba hal-hal untuk diri sendiri dan lihat apa yang cocok untuk Anda.

Brad Clawsie
sumber
1
FWIW, aritmatika floating point lebih rumit daripada RE, tetapi tampak lebih sederhana. Waspadalah! (Setidaknya RE yang rumit cenderung terlihat berbahaya.)
Donal Fellows
3

Favorit saya, jawaban mendalam untuk ini diberikan oleh Rob Pike yang terkenal dalam posting blog yang direproduksi dari komentar kode Google internal: http://commandcenter.blogspot.ch/2011/08/ regular-expressions-in-lexing- and.html

Rangkumannya bukan karena mereka buruk , tetapi mereka sering digunakan untuk tugas-tugas yang belum tentu cocok, terutama ketika menyangkut lexing dan parsing beberapa input.

Ekspresi reguler sulit untuk ditulis, sulit untuk menulis dengan baik, dan bisa relatif mahal dibandingkan dengan teknologi lain ... Lexers, di sisi lain, cukup mudah untuk menulis dengan benar (jika tidak sekompak), dan sangat mudah untuk diuji. Pertimbangkan untuk menemukan pengidentifikasi alfanumerik. Tidak terlalu sulit untuk menulis regexp (sesuatu seperti "[a-ZA-Z _] [a-ZA-Z_0-9] *"), tetapi sebenarnya tidak terlalu sulit untuk menulis sebagai loop sederhana. Namun, kinerja loop akan jauh lebih tinggi dan akan melibatkan lebih sedikit kode di bawah selimut. Perpustakaan ekspresi reguler adalah hal yang besar. Menggunakan satu untuk mengurai pengidentifikasi seperti menggunakan Ferrari untuk pergi ke toko untuk membeli susu.

Dia mengatakan lebih dari itu, dengan alasan bahwa ekspresi reguler berguna, misalnya pencocokan pola yang sekali pakai dalam editor teks tetapi jarang digunakan dalam kode yang dikompilasi, dan sebagainya. Ini layak dibaca.

dan mackinlay
sumber
0

Ini terkait dengan epigram # 34 Alan Perlis:

String adalah struktur data yang mencolok dan di mana-mana dilewatkan ada banyak duplikasi proses. Ini adalah kendaraan yang sempurna untuk menyembunyikan informasi.

Jadi jika Anda memilih string karakter sebagai struktur data Anda (dan, tentu saja, kode berbasis regex sebagai algoritma untuk memanipulasinya), Anda memiliki masalah, bahkan jika itu berfungsi: desain yang buruk di sekitar representasi data yang tidak sesuai yang sulit untuk memperpanjang, dan tidak efisien.

Namun, seringkali itu tidak berhasil: masalah asli tidak terpecahkan, dan dalam hal ini Anda memiliki dua masalah.

Kaz
sumber
0

Regex banyak digunakan untuk penguraian teks yang cepat dan kotor. Mereka adalah alat yang hebat untuk mengekspresikan pola yang sedikit lebih kompleks dari sekadar pencocokan string biasa.

Namun ketika regex mendapatkan masalah server yang lebih kompleks, angkat kepala.

  1. Sintaks regex dioptimalkan untuk pencocokan sederhana, sebagian besar karakter cocok sendiri. Itu bagus untuk pola sederhana tetapi sekali Anda berakhir dengan lebih dari beberapa level bersarang Anda berakhir dengan sesuatu yang tampak lebih seperti derau baris daripada kode yang terstruktur dengan baik. Saya kira Anda bisa menulis regex sebagai serangkaian string bersambung dengan lekukan dan komentar di antara untuk menunjukkan struktur kode tetapi tampaknya jarang hal itu benar-benar terjadi.
  2. Hanya jenis pencocokan teks tertentu yang cocok untuk regex. Seringkali Anda menemukan diri Anda mendapatkan parser berbasis regex cepat dan kotor untuk beberapa jenis bahasa markup bekerja tetapi kemudian Anda mencoba untuk menutupi lebih banyak kasus sudut dan Anda menemukan regex menjadi lebih dan lebih kompleks dan kurang dan kurang dapat dibaca
  3. Kompleksitas waktu suatu regex mungkin tidak obvoius. Ini tidak sulit untuk berakhir dengan pola yang bekerja sangat baik ketika cocok tetapi memiliki kompleksitas O (2 ^ n) dalam kasus-kasus tertentu yang tidak cocok .

Jadi itu semua terlalu mudah untuk memulai dengan masalah pemrosesan teks, menerapkan ekspresi reguler untuk itu dan berakhir dengan dua masalah, masalah asli yang Anda coba selesaikan dan berurusan dengan ekspresi reguler yang berusaha untuk dipecahkan (tetapi tidak menyelesaikan dengan benar) masalah aslinya.

Peter Green
sumber