Ekspresi reguler yang dapat dibaca tanpa kehilangan kekuatannya?

77

Banyak programmer mengetahui kegembiraan membuat ekspresi reguler yang cepat, akhir-akhir ini sering kali dengan bantuan beberapa layanan web, atau lebih tradisional pada prompt interaktif, atau mungkin menulis skrip kecil yang memiliki ekspresi reguler dalam pengembangan, dan kumpulan kasus uji . Dalam kedua kasus tersebut, prosesnya berulang dan cukup cepat: tetap meretas string yang tampak samar sampai cocok dan menangkap apa yang Anda inginkan dan akan menolak apa yang tidak Anda inginkan.

Untuk kasus sederhana, hasilnya mungkin seperti ini, sebagai regexp Java:

Pattern re = Pattern.compile(
  "^\\s*(?:(?:([\\d]+)\\s*:\\s*)?(?:([\\d]+)\\s*:\\s*))?([\\d]+)(?:\\s*[.,]\\s*([0-9]+))?\\s*$"
);

Banyak programmer juga tahu sakitnya harus mengedit ekspresi reguler, atau hanya kode sekitar ekspresi reguler dalam basis kode legacy. Dengan sedikit pengeditan untuk membaginya, regexp di atas masih sangat mudah dipahami bagi siapa pun yang cukup akrab dengan regexps, dan seorang veteran regexp harus segera melihat apa yang dilakukannya (jawab di akhir posting, kalau-kalau ada yang menginginkan latihan tersebut) mencari tahu sendiri).

Namun, hal-hal yang tidak perlu menjadi jauh lebih kompleks untuk regexp menjadi hal yang benar-benar hanya untuk menulis, dan bahkan dengan dokumentasi yang rajin (yang semua orang tentu saja lakukan untuk semua regexps kompleks yang mereka tulis ...), memodifikasi regexps menjadi sebuah tugas yang menakutkan. Ini bisa menjadi tugas yang sangat berbahaya juga, jika regexp tidak diuji unit dengan hati-hati (tetapi setiap orang tentu saja memiliki tes unit komprehensif untuk semua regexps kompleks mereka, baik positif maupun negatif ...).

Jadi, singkatnya, apakah ada solusi baca-tulis / alternatif untuk ekspresi reguler tanpa kehilangan kekuatannya? Bagaimana regexp di atas akan terlihat seperti dengan pendekatan alternatif? Bahasa apa pun baik-baik saja, meskipun solusi multi-bahasa adalah yang terbaik, sampai tingkat regexps multi-bahasa.


Dan kemudian, apa yang dilakukan regexp sebelumnya adalah ini: parsing string angka dalam format 1:2:3.4, menangkap setiap angka, di mana spasi diizinkan dan hanya 3diperlukan.

Hyde
sumber
2
hal terkait pada SO: stackoverflow.com/a/143636/674039
wim
24
Membaca / mengedit regex sebenarnya sepele jika Anda tahu apa yang seharusnya ditangkap. Anda mungkin pernah mendengar tentang fitur yang jarang digunakan ini di sebagian besar bahasa yang disebut "komentar". Jika Anda tidak meletakkan satu di atas regex yang kompleks menjelaskan apa fungsinya, Anda akan membayar harganya nanti. Juga, tinjauan kode.
TC1
2
Dua opsi untuk membersihkan ini tanpa benar-benar memecahnya menjadi potongan-potongan kecil. Ada atau tidaknya mereka bervariasi dari satu bahasa ke bahasa lainnya. (1) regex baris diperpanjang, di mana spasi putih di regex diabaikan (kecuali melarikan diri) dan formulir komentar baris tunggal ditambahkan, sehingga Anda dapat memecahnya menjadi potongan logis dengan lekukan, spasi, dan komentar. (2) bernama kelompok tangkap, di mana Anda dapat memberikan nama untuk setiap tanda kurung, yang keduanya menambahkan beberapa dokumentasi diri, dan secara otomatis mengisi hash pertandingan - jauh lebih baik daripada array pertandingan yang diindeks secara numerik atau variabel $ N.
Ben Lee
3
Bagian dari masalah adalah bahasa regex itu sendiri, dan pilihan bersejarah yang buruk dalam desainnya yang diseret seperti bagasi. Dalam bahasa waras, tanda kurung pengelompokan adalah perangkat sintaksis murni untuk membentuk pohon parse. Tetapi dalam implementasi regex kembali ke Unix mereka memiliki semantik: mengikat register untuk pertandingan subekspresi. Jadi, Anda memerlukan kurung yang lebih rumit dan jelek hanya untuk mencapai pengelompokan murni!
Kaz
2
Sebenarnya bukan jawaban yang praktis, tetapi mungkin berguna untuk menyebutkan bahwa kekuatan ekspresi reguler sama persis dengan otomat terbatas. Artinya, regex dapat memvalidasi / mengurai kelas string yang sama divalidasi dan diurai oleh robot hingga. Oleh karena itu, representasi regex yang dapat dibaca manusia mungkin harus dapat dengan cepat membuat grafik, dan saya percaya sebagian besar bahasa berbasis teks benar-benar buruk dalam hal itu; itu sebabnya kami menggunakan alat visual untuk hal-hal seperti itu. Lihatlah hackingoff.com/compilers/regular-expression-to-nfa-dfa untuk mendapatkan inspirasi.
damix911

Jawaban:

80

Sejumlah orang telah menyebutkan komposisi dari bagian yang lebih kecil, tetapi belum ada yang memberikan contoh, jadi inilah milik saya:

string number = "(\\d+)";
string unit = "(?:" + number + "\\s*:\\s*)";
string optionalDecimal = "(?:\\s*[.,]\\s*" + number + ")?";

Pattern re = Pattern.compile(
  "^\\s*(?:" + unit + "?" + unit + ")?" + number + optionalDecimal + "\\s*$"
);

Bukan yang paling mudah dibaca, tapi saya merasa lebih jelas dari aslinya.

Selain itu, C # memiliki @operator yang dapat ditambahkan ke string untuk menunjukkan bahwa itu harus diambil secara harfiah (tidak ada karakter escape), jadi numberakan menjadi@"([\d]+)";

Bobson
sumber
Baru saja perhatikan bagaimana keduanya [\\d]+dan [0-9]+seharusnya adil \\d+(well, beberapa mungkin menemukan [0-9]+lebih mudah dibaca). Saya tidak akan mengedit pertanyaan, tetapi Anda mungkin ingin memperbaiki jawaban ini.
hyde
@hyde - Tangkapan yang bagus. Secara teknis mereka bukan hal yang sama - \dakan cocok dengan apa pun yang dianggap bilangan, bahkan dalam sistem penomoran lainnya (Cina, Arab, dll.), Sementara [0-9]hanya akan cocok dengan angka standar. Saya melakukan standarisasi \\d, dan memasukkannya ke dalam optionalDecimalpola.
Bobson
42

Kunci untuk mendokumentasikan ekspresi reguler adalah mendokumentasikannya. Terlalu sering orang melemparkan apa yang tampak sebagai derau baris dan membiarkannya begitu saja.

Dalam perl , /xoperator di akhir ekspresi reguler menekan spasi putih memungkinkan seseorang untuk mendokumentasikan ekspresi reguler.

Ekspresi reguler di atas kemudian menjadi:

$re = qr/
  ^\s*
  (?:
    (?:       
      ([\d]+)\s*:\s*
    )?
    (?:
      ([\d]+)\s*:\s*
    )
  )?
  ([\d]+)
  (?:
    \s*[.,]\s*([\d]+)
  )?
  \s*$
/x;

Ya, ini sedikit memakan spasi vertikal, meskipun orang bisa mempersingkatnya tanpa mengorbankan terlalu banyak keterbacaan.

Dan kemudian, apa yang dilakukan regexp sebelumnya adalah ini: parsing serangkaian angka dalam format 1: 2: 3.4, menangkap setiap angka, di mana spasi diizinkan dan hanya 3 yang diperlukan.

Melihat ungkapan reguler ini orang dapat melihat cara kerjanya (dan tidak bekerja). Dalam hal ini, regex ini akan cocok dengan string 1.

Pendekatan serupa dapat diambil dalam bahasa lain. Opsi python re.VERBOSE bekerja di sana.

Perl6 (contoh di atas adalah untuk perl5) mengambil ini lebih jauh dengan konsep aturan yang mengarah pada struktur yang bahkan lebih kuat daripada PCRE (ini menyediakan akses ke tata bahasa lain (bebas konteks dan sensitif konteks) daripada yang biasa dan diperpanjang reguler).

Di Jawa (di mana contoh ini diambil dari), seseorang dapat menggunakan penggabungan string untuk membentuk regex.

Pattern re = Pattern.compile(
  "^\\s*"+
  "(?:"+
    "(?:"+
      "([\\d]+)\\s*:\\s*"+  // Capture group #1
    ")?"+
    "(?:"+
      "([\\d]+)\\s*:\\s*"+  // Capture group #2
    ")"+
  ")?"+ // First groups match 0 or 1 times
  "([\\d]+)"+ // Capture group #3
  "(?:\\s*[.,]\\s*([0-9]+))?"+ // Capture group #4 (0 or 1 times)
  "\\s*$"
);

Memang, ini menciptakan lebih banyak "dalam string yang mungkin menyebabkan kebingungan di sana, dapat lebih mudah dibaca (terutama dengan penyorotan sintaks pada sebagian besar IDE) dan didokumentasikan.

Kuncinya adalah mengenali kekuatan dan "menulis sekali" sifat yang sering jatuh ke ekspresi reguler. Menulis kode untuk menghindari hal ini secara defensif sehingga ekspresi reguler tetap jelas dan dapat dimengerti adalah kuncinya. Kami memformat kode Java untuk kejelasan - ekspresi reguler tidak berbeda ketika bahasa memberi Anda opsi untuk melakukannya.


sumber
13
Ada perbedaan besar antara "mendokumentasikan" dan "menambahkan jeda baris".
4
@JonofAllTrades Membuat kode dapat dibaca adalah langkah pertama untuk apa pun. Menambahkan jeda baris juga memungkinkan seseorang untuk menambahkan komentar untuk subset RE tersebut pada baris yang sama (sesuatu yang lebih sulit dilakukan pada satu baris panjang teks ekspresi reguler).
2
@JonofAllTrades, saya sangat tidak setuju. "Mendokumentasikan" dan "menambahkan jeda baris" tidak jauh berbeda karena keduanya melayani tujuan yang sama - membuat kode lebih mudah dimengerti. Dan untuk kode yang diformat dengan buruk, "menambahkan jeda baris" melayani tujuan itu jauh lebih baik daripada menambahkan dokumentasi.
Ben Lee
2
Menambahkan jeda baris adalah awal, tetapi sekitar 10% dari pekerjaan. Jawaban lain memberikan lebih spesifik, yang bermanfaat.
26

Mode "verbose" yang ditawarkan oleh beberapa bahasa dan perpustakaan adalah salah satu jawaban untuk masalah ini. Dalam mode ini, spasi putih dalam string regexp dihapus (jadi Anda harus menggunakan \s) dan komentar dimungkinkan. Berikut adalah contoh singkat dalam Python yang mendukung ini secara default:

email_regex = re.compile(r"""
    ([\w\.\+]+) # username (captured)
    @
    \w+         # minimal viable domain part
    (?:\.w+)    # rest of the domain, after first dot
""", re.VERBOSE)

Dalam bahasa apa pun yang tidak, menerapkan penerjemah dari verbose ke mode "normal" harus menjadi tugas yang sederhana. Jika Anda khawatir tentang keterbacaan regexps Anda, Anda mungkin akan membenarkan investasi waktu ini dengan mudah.

Xion
sumber
15

Setiap bahasa yang menggunakan regex memungkinkan Anda untuk menyusunnya dari blok yang lebih sederhana agar lebih mudah dibaca, dan dengan sesuatu yang lebih rumit daripada (atau serumit) contoh Anda, Anda harus mengambil keuntungan dari opsi itu. Masalah khusus dengan Jawa dan banyak bahasa lainnya adalah bahwa mereka tidak memperlakukan ekspresi reguler sebagai warga negara "kelas satu", sebaliknya mengharuskan mereka untuk menyelinap ke dalam bahasa melalui string literal. Ini berarti banyak tanda kutip dan garis miring terbalik yang sebenarnya bukan bagian dari sintaks regex dan membuat hal-hal sulit dibaca, dan itu juga berarti bahwa Anda tidak bisa lebih mudah dibaca daripada itu tanpa secara efektif mendefinisikan bahasa mini dan penerjemah Anda sendiri.

Cara prototipikal yang lebih baik untuk mengintegrasikan ekspresi reguler tentu saja Perl, dengan opsi spasi putih dan operator regex-quote. Perl 6 memperluas konsep membangun regex dari bagian ke tata bahasa rekursif yang sebenarnya, yang jauh lebih baik untuk digunakan itu benar-benar tidak ada perbandingan sama sekali. Bahasa itu mungkin telah ketinggalan zaman, tetapi dukungan regexnya adalah The Good Stuff (tm).

Kilian Foth
sumber
1
Dengan "blok sederhana" yang disebutkan di awal jawaban, apakah maksud Anda hanya penggabungan string, atau sesuatu yang lebih maju?
hyde
7
Maksud saya mendefinisikan sub-ekspresi sebagai string string yang lebih pendek, menugaskan mereka ke variabel lokal dengan nama yang bermakna, dan kemudian menggabungkannya. Saya menemukan nama-nama lebih penting untuk dibaca daripada hanya perbaikan tata letak.
Kilian Foth
11

Saya suka menggunakan Expresso: http://www.ultrapico.com/Expresso.htm

Aplikasi gratis ini memiliki fitur-fitur berikut yang menurut saya berguna dari waktu ke waktu:

  • Anda cukup menyalin dan menempelkan regex Anda dan aplikasi akan menguraikannya untuk Anda
  • Setelah regex Anda ditulis, Anda dapat mengujinya langsung dari aplikasi (aplikasi tersebut akan memberi Anda daftar tangkapan, penggantian ...)
  • Setelah Anda mengujinya, itu akan menghasilkan kode C # untuk mengimplementasikannya (perhatikan bahwa kode tersebut akan berisi penjelasan tentang regex Anda).

Misalnya, dengan regex yang baru saja Anda kirim, akan terlihat seperti: Layar sampel dengan regex yang awalnya diberikan

Tentu saja, mencobanya bernilai ribuan kata yang menggambarkannya. Harap perhatikan juga bahwa saya mencatat terkait dengan cara apa pun dengan editor aplikasi ini.

E. Jaep
sumber
4
maukah Anda menjelaskan hal ini secara lebih rinci - bagaimana dan mengapa itu menjawab pertanyaan yang diajukan? "Jawaban khusus tautan" tidak diterima di Stack Exchange
agas
5
@gnat Maaf tentang itu. Anda benar sekali. Saya harap jawaban saya yang diedit memberikan lebih banyak wawasan.
E. Jaep
9

Untuk beberapa hal, mungkin membantu untuk hanya menggunakan tata bahasa seperti BNF. Ini bisa lebih mudah dibaca daripada ekspresi reguler. Alat seperti GoldParser Builder kemudian dapat mengubah tata bahasa menjadi parser yang melakukan pengangkatan berat untuk Anda.

Tata bahasa BNF, EBNF, dll. Bisa lebih mudah dibaca dan dibuat daripada ekspresi reguler yang rumit. GOLD adalah salah satu alat untuk hal-hal seperti itu.

Tautan wiki c2 di bawah ini memiliki daftar alternatif yang memungkinkan yang dapat di-Google, dengan beberapa diskusi tentang mereka. Ini pada dasarnya adalah tautan "lihat juga" untuk melengkapi rekomendasi mesin tata bahasa saya:

Alternatif Untuk Ekspresi Reguler

Mengambil "alternatif" untuk berarti "fasilitas semantik yang setara dengan sintaks yang berbeda", setidaknya ada alternatif ini untuk / dengan RegularExpressions:

  • Ekspresi reguler dasar
  • Ekspresi reguler "Diperpanjang"
  • Ekspresi reguler yang kompatibel dengan Perl
  • ... dan banyak varian lainnya ...
  • Sintaks RE gaya SNOBOL (SnobolLanguage, IconLanguage)
  • Sintaks SRE (RE sebagai EssExpressions)
  • sintaks FSM yang berbeda
  • Tata bahasa persimpangan kondisi terbatas (cukup ekspresif)
  • ParsingExpressionGrammars, seperti pada OMetaLanguage dan LuaLanguage ( http://www.inf.puc-rio.br/~roberto/lpeg/lpeg.html )
  • Mode parse dari RebolLanguage
  • ProbabilitasBerdasarkanParsing ...
Nick P
sumber
maukah Anda menjelaskan lebih lanjut tentang apa yang dilakukan tautan ini dan apa manfaatnya? "Jawaban khusus tautan" tidak diterima di Stack Exchange
agas
1
Selamat datang di Programmer, Nick P. Harap abaikan downvote / r, tapi baca halaman di meta yang terhubung dengan @gnat.
Christoffer Lette
@ Christoffer Lette Hargai balasan Anda. Akan mencoba untuk mengingat ini di posting mendatang. Komentar @ gnat Paulo Scardine mencerminkan niat posting saya. Tata bahasa BNF, EBNF, dll. Bisa lebih mudah dibaca dan dibuat daripada ekspresi reguler yang rumit. GOLD adalah salah satu alat untuk hal-hal seperti itu. Tautan c2 memiliki daftar alternatif yang memungkinkan yang dapat di-Google, dengan beberapa diskusi tentang mereka. Pada dasarnya itu adalah "lihat juga" tautan untuk melengkapi rekomendasi tata bahasa saya.
Nick P
6

Ini adalah pertanyaan lama dan saya tidak melihat penyebutan Verbal, jadi saya pikir saya akan menambahkan informasi itu di sini juga untuk para pencari masa depan. Ekspresi verbal secara khusus dirancang untuk membuat regex manusia dapat dipahami, tanpa perlu mempelajari makna simbol dari regex. Lihat contoh berikut. Saya pikir ini yang terbaik dari apa yang Anda minta.

// Create an example of how to test for correctly formed URLs
var tester = VerEx()
    .startOfLine()
    .then('http')
    .maybe('s')
    .then('://')
    .maybe('www.')
    .anythingBut(' ')
    .endOfLine();

// Create an example URL
var testMe = 'https://www.google.com';

// Use RegExp object's native test() function
if (tester.test(testMe)) {
    alert('We have a correct URL '); // This output will fire}
} else {
    alert('The URL is incorrect');
}

console.log(tester); // Outputs the actual expression used: /^(http)(s)?(\:\/\/)(www\.)?([^\ ]*)$/

Contoh ini untuk javascript, Anda dapat menemukan perpustakaan ini sekarang untuk banyak bahasa pemrograman.

Parivar Saraff
sumber
2
Ini luar biasa!
Jeremy Thompson
3

Cara paling sederhana adalah dengan tetap menggunakan regex tetapi membangun ekspresi Anda dari penulisan ekspresi yang lebih sederhana dengan nama deskriptif misalnya http://www.martinfowler.com/bliki/ComposedRegex.html (dan ya ini dari string concat)

namun sebagai alternatif, Anda juga bisa menggunakan parser combin library misalnya http://jparsec.codehaus.org/ yang akan memberi Anda parser yang layak secara rekursif. lagi-lagi kekuatan sesungguhnya di sini berasal dari komposisi (komposisi fungsional kali ini).

jk.
sumber
3

Saya pikir itu layak menyebutkan ekspresi grok logstash . Grok dibangun berdasarkan gagasan menyusun ekspresi parsing panjang dari yang lebih pendek. Ini memungkinkan pengujian yang mudah terhadap blok-blok bangunan ini dan dilengkapi dengan lebih dari 100 pola yang umum digunakan . Selain pola-pola ini, ini memungkinkan penggunaan semua sintaks ekspresi reguler.

Pola di atas dinyatakan dalam grok adalah (Saya menguji di aplikasi debugger tetapi bisa salah):

"(( *%{NUMBER:a} *:)? *%{NUMBER:b} *:)? *%{NUMBER:c} *(. *%{NUMBER:d} *)?"

Bagian dan ruang opsional membuatnya tampak sedikit lebih jelek dari biasanya, tetapi baik di sini maupun dalam kasus lain, menggunakan grok dapat membuat hidup seseorang jauh lebih baik.

yoniLavi
sumber
2

Di F # Anda memiliki modul FsVerbalExpressions . Ini memungkinkan Anda untuk menyusun Regex dari ekspresi verbal, juga memiliki beberapa regex yang sudah dibuat sebelumnya (seperti URL).

Salah satu contoh untuk sintaks ini adalah sebagai berikut:

let groupName =  "GroupNumber"

VerbEx()
|> add "COD"
|> beginCaptureNamed groupName
|> any "0-9"
|> repeatPrevious 3
|> endCapture
|> then' "END"
|> capture "COD123END" groupName
|> printfn "%s"

// 123

Jika Anda tidak terbiasa dengan sintaks F #, groupName adalah string "GroupNumber".

Kemudian mereka membuat Ekspresi Verbal (VerbEx) yang mereka buat sebagai "COD (? <GroupNumber> [0-9] {3}) END". Yang kemudian mereka uji pada string "COD123END", di mana mereka mendapatkan grup tangkapan bernama "GroupNumber". Ini menghasilkan 123.

Jujur saya menemukan regex normal jauh lebih mudah untuk dipahami.

CodeMonkey
sumber
-2

Pertama, pahami bahwa kode yang hanya berfungsi adalah kode yang buruk. Kode yang baik juga perlu melaporkan kesalahan yang ditemukan secara akurat.

Misalnya, jika Anda sedang menulis fungsi untuk mentransfer uang tunai dari akun satu pengguna ke akun pengguna lain; Anda tidak akan hanya mengembalikan boolean "berhasil atau gagal" karena itu tidak memberi tahu si penelepon tentang apa yang salah dan tidak mengizinkan penelepon memberi tahu pengguna dengan benar. Sebagai gantinya, Anda mungkin memiliki satu set kode kesalahan (atau serangkaian pengecualian): tidak dapat menemukan akun tujuan, dana yang tidak mencukupi di akun sumber, izin ditolak, tidak dapat terhubung ke database, terlalu banyak memuat (coba lagi nanti), dll. .

Sekarang pikirkan tentang "parsing serangkaian angka dalam format 1: 2: 3,4" misalnya. Semua regex lakukan adalah melaporkan "lulus / gagal" yang tidak memungkinkan umpan balik yang memadai untuk disajikan kepada pengguna (apakah umpan balik ini adalah pesan kesalahan dalam log, atau GUI interaktif di mana kesalahan ditampilkan merah sebagai tipe pengguna, atau apa pun yang lain). Apa jenis kesalahan yang gagal dijelaskan dengan benar? Karakter buruk di angka pertama, angka pertama terlalu besar, titik dua hilang setelah angka pertama, dll.

Untuk mengubah "kode buruk yang hanya berfungsi" menjadi "kode bagus yang menyediakan kesalahan deskriptif yang memadai" Anda harus memecah regex menjadi banyak regex yang lebih kecil (biasanya, regex yang sangat kecil sehingga lebih mudah untuk melakukannya tanpa regex di tempat pertama) ).

Membuat kode dapat dibaca / dipelihara hanyalah konsekuensi tidak disengaja dari membuat kode tersebut baik.

Brendan
sumber
6
Mungkin bukan asumsi yang bagus. Milik saya adalah karena A) Ini tidak menjawab pertanyaan ( Bagaimana membuatnya dapat dibaca?), B) Pencocokan ekspresi reguler adalah lulus / gagal, dan jika Anda memecahnya ke titik di mana Anda dapat mengatakan dengan tepat mengapa gagal, Anda kehilangan banyak kekuatan dan kecepatan, dan menambah kompleksitas, C) Tidak ada indikasi dari pertanyaan bahwa ada bahkan kemungkinan pertandingan gagal - itu hanya pertanyaan tentang membuat Regex dapat dibaca. Ketika Anda memiliki kendali atas data yang masuk dan / atau memvalidasi sebelumnya, Anda dapat menganggapnya valid.
Bobson
A) Memecahnya menjadi potongan-potongan kecil membuatnya lebih mudah dibaca (sebagai konsekuensi membuatnya baik). C) Di mana string yang tidak dikenal / tidak tervalidasi memasukkan perangkat lunak yang pengembang waras akan parsing (dengan pelaporan kesalahan) pada titik itu dan mengubah data menjadi bentuk yang tidak perlu reparsing - regex tidak diperlukan setelah itu. B) adalah omong kosong yang hanya berlaku untuk kode buruk (lihat poin A dan C).
Brendan
Pergi dari C Anda: Bagaimana jika ini adalah logika validasinya? Kode OP dapat persis seperti yang Anda sarankan - memvalidasi input, melaporkan jika tidak valid, dan mengonversinya menjadi bentuk yang dapat digunakan (melalui tangkapan). Yang kita miliki hanyalah ekspresi itu sendiri. Bagaimana Anda menyarankan untuk menguraikannya selain dengan regex? Jika Anda menambahkan beberapa kode sampel yang akan mencapai hasil yang sama, saya akan menghapus downvote saya.
Bobson
Jika ini "C: Memvalidasi (dengan pelaporan kesalahan)" maka itu kode buruk karena pelaporan kesalahan buruk. Jika gagal; apakah itu karena stringnya NULL, atau karena angka pertama memiliki terlalu banyak digit, atau karena pemisah pertama tidak :? Bayangkan kompiler yang hanya memiliki satu pesan kesalahan ("ERROR") yang terlalu bodoh untuk memberi tahu pengguna apa masalahnya. Sekarang bayangkan ribuan situs web yang sama bodohnya dan menampilkan (mis.) "Alamat email buruk" dan tidak lebih.
Brendan
Juga, bayangkan operator help desk setengah terlatih mendapatkan laporan bug dari pengguna yang benar-benar tidak terlatih yang mengatakan: Perangkat lunak berhenti bekerja - baris terakhir dalam log perangkat lunak adalah "KESALAHAN: Gagal mengekstraksi nomor versi minor dari string versi '1: 2-3.4 '(diharapkan titik dua setelah nomor kedua) "
Brendan