Kami melewati tantangan dari Callum Macrae 100%

Saya sarankan mencoba menyelesaikan 10 tes regex dari Callum Macrae. Tidak seperti analisis saya sebelumnya tentang tantangan , tidak ada tugas yang terus terang sederhana dan bahkan rata-rata. Seperti yang mereka katakan - hanya regex, hanya hardcore.


Karena tantangannya cukup rumit, tidak perlu mengikuti semua aturan seperti saya, setiap kelulusan tes adalah 100% - berarti Anda adalah seorang profesional super. Selamat datang!


Ya, saya tahu, tantangan ini sudah diposting sekali. Tetapi penulis posting tidak menyajikan solusi kerja, dan dalam komentar, orang tidak dapat menyelesaikan 4 masalah lebih lanjut, dan lebih sering bahkan tidak mengerti arti dari tugas dan apa yang mereka inginkan dari mereka.


Oleh karena itu, saya mempostingnya lagi, dengan terjemahan terperinci, penjelasan dan semua roti yang mengandalkan.


Tugas 1 - sorot kata-kata rangkap


http://callumacrae.imtqy.com/regex-tuesday/challenge1.html


Ada satu set kalimat, dalam kalimat ini mungkin ada kata-kata rangkap. Anda perlu menyorot kata-kata yang berulang.


Contoh:


This is is a test 

Dalam hal ini, kata "adalah" diulang dua kali, disorot dengan huruf tebal:


 This is <strong>is</strong> a test 

Petunjuk

Penting untuk menemukan pengulangan kata-kata, dan kata-kata dipisahkan oleh spasi, oleh karena itu - diperlukan karakter spasi. Dalam ekspresi reguler, secara teknis dimungkinkan untuk menemukan pengulangan hanya melalui tautan belakang.


Solusi

Ekspresi:


 /\b([\w']+)\s(\1)\b/gi 

Penggantian:


 $1 <strong>$2</strong> 

Solusi parsing
  • "\ b" - harus dimulai dari batas kata
  • "([\ w '] +)" - sejumlah huruf, angka, dan apostrof (Anda juga dapat menyelesaikannya dengan selain spasi ) dan pastikan untuk mengambilnya dalam grup, karena Selanjutnya, cari pengulangan dari grup ini.
  • "\ s (\ 1)" - karena kita tahu bahwa pengulangan datang setelah spasi, kita meletakkan spasi "\ s" dan kemudian kita menulis bahwa setelah itu pengulangan dari grup pertama yang sebelumnya ditangkap "" (\ 1) "harus mengikuti.
  • "\ b" - pengulangan harus diakhiri dengan batas kata, jika tidak kita berisiko hanya menangkap sebagian kata saja.

Tugas 2 - Skala abu-abu


http://callumacrae.imtqy.com/regex-tuesday/challenge2.html


Ada kode warna dalam format yang berbeda, tugasnya adalah menemukan semua nuansa abu-abu.


Contoh kode yang valid:


 #eEe #6F6F6F rgb(2.5, 2.5,2.5) hsl(0, 10%, 100%) 

Contoh kode yang tidak valid:


 #eEf #11111e rgb(1.5%, 1.5%, 1.6%) hsl(20, 20%, 20%) 

Penjelasan Kode

Pertanyaan paling penting dalam tugas ini adalah apa yang dianggap abu-abu.


Menurut Wikipedia, grey adalah:


Banyak warna yang diperoleh dengan menggabungkan tiga warna utama dari model warna RGB - merah, hijau dan biru dalam konsentrasi yang sama .

Kode yang dimulai dengan # adalah format hex, tersedia dalam dua bentuk. Disingkat, tiga karakter (#rgb) dan penuh, enam karakter $ rrggbb. Di mana r, g, b adalah tiga warna primer.
Kode rgb (r, g, b) persis sama, hanya ditulis dalam angka dari 0 hingga 255.
Format hsl sedikit lebih rumit, angka di sini berarti nada, saturasi, dan cahaya. Untuk memahami dalam kondisi apa tiga warna utama diperoleh dalam proporsi yang sama, misalnya, Anda dapat bermain-main dengan editor visual ini .


Petunjuk

Untuk hex yang disingkat, kemunculan yang benar adalah pengulangan dari ketiga karakter, misalnya #aaa. Untuk hex penuh, ulangi dua karakter, misalnya #efefef. Untuk rgb digital, ulangi digit, misalnya rgb (2, 2, 2). Memahami format hsl sedikit lebih rumit, tetapi masih mengetahui di atas, Anda dapat memahami bahwa di sini warna abu-abu adalah warna di mana nada adalah 0 atau saturasi adalah 0 atau 100.


Dengan demikian, seperti pada tugas sebelumnya, Anda harus menggunakan tautan balik. Ekspresi reguler yang dihasilkan akan besar (ini normal), karena Anda perlu mempertimbangkan banyak opsi yang berbeda, termasuk yang salah ditulis.


Solusi
 /^(?:#(\w)\1\1|#(\w{2})\2\2|rgb\(((?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])%?(?:\.\d+)?),[ ]?[0]*\3,[ ]?[0]*\3\)|rgba\(([\d.]+%?),[0 ]*\4,[0 ]*\4,[^)]+\)|hsla?\([\d.]+,[ ]*(0%[^)]+|[\d.]+%,[ ]*(0|100)%[^\)]*)\))$/i 

Solusi parsing

Rugular terpisah ditulis untuk setiap warna, kami akan menganalisisnya secara terpisah:


 #(\w)\1\1 

  • "(\ w)" ambil satu karakter tunggal dalam grup.
  • "\ 1 \ 1" - dan tunjukkan bahwa itu harus diulang 2 kali.

Untuk dua karakter hal yang sama - saya tidak akan ulangi.


 rgb\(((?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])%?(?:\.\d+)?),[ ]?[0]*\3,[ ]?[0]*\3\) 

Saya ingin menulis "rgba?", Tetapi sebuah kasus dimungkinkan ketika parameter keempat ditentukan dalam rgb (), jadi rgb dan rgba perlu dijelaskan secara terpisah:


  • "\ d {1,2} | 1 \ d {2} | 2 [0-4] \ d | 25 [0-5]" - rentangnya dari 0 hingga 255. Saya tidak akan menganalisisnya secara rinci, Anda dapat melihat tugas 5 di sini .
  • "(?: \. \ d +)?" - grup opsional yang nomornya tidak ditentukan. Suatu titik dan angka setelah titik dimungkinkan (ini adalah untuk angka yang bukan bilangan bulat).
  • ", []? [0] * \ 3" - koma wajib, diikuti oleh 0 atau 1 spasi, 0 atau banyak nol, setelah itu nilai kelompok yang sebelumnya ditangkap harus diulang.

Dalam rgba () - hal yang sama, tetapi diperlukan 4 parameter.


 hsla?\([\d.]+,[ ]*(0%[^)]+|[\d.]+%,[ ]*(0|100)%[^\)]*)\) 

Di sini, dengan cara yang baik, Anda juga perlu memisahkan hsl dan hsla, tetapi tidak ada kasus seperti itu dalam kasus uji, oleh karena itu, menulis sedikit "hsla?"


  • "[\ d.] +, [] *" - pertama kali muncul angka yang diperlukan "[\ d.] +" (termasuk bukan seluruh angka) dengan koma wajib dan spasi opsional "[] *".
  • "(0% [^)] + | [\ d.] +%, [] * (0 | 100)% [^)] *" - dan kemudian dua opsi dimungkinkan: 1) di mana 0% datang pertama dan kemudian apa saja karakter selain karakter penutup braket [^)] +; 2) ada angka dengan tanda persen wajib dan koma "[\ d.] +%," Dan kemudian 0% atau 100% "(0 | 100)%".

Tugas 3 - cari tanggal


http://callumacrae.imtqy.com/regex-tuesday/challenge3.html


Ada daftar tanggal, dari tanggal-tanggal ini menemukan tanggal dari 1000 hingga 2012 secara tertulis dalam format YYYY / MM / DD HH: MM (: SS). Di mana setiap huruf adalah nomor wajib, dan dalam kurung bukanlah prasyarat.


Contoh


 2001/09/30 23:59:11 

Petunjuk

"[0-9]" bukan rentang angka, ini adalah ekspresi yang berarti bahwa satu karakter dari 0-9 valid. Dalam ekspresi reguler tidak ada rentang untuk angka besar, tetapi dari potongan kecil seperti itu Anda dapat membuat ekspresi reguler yang mencakup rentang yang diinginkan. Contoh: "1 [0-9]" - berkisar dari 10 hingga 19.


Solusi
 /^(1[\d]{3}|200\d|201[0-2])\/(0[1-9]|1[0-2])\/(0[1-9]|1[0-9]|2[0-9]|3[0-2])\s(0[0-9]|1[0-9]|2[0-3]):([0-5][\d])(:([0-5][\d]))?$/ 

Solusi parsing
  • Tahun yang valid adalah "(1 [\ d] {3} | 200 \ d | 201 [0-2])", di mana dalam urutan 1000 hingga 1999, dari 2000 hingga 2009, dari 2010 hingga 2012.
  • Bulan "(0 [1-9] | 1 [0-2])". Dari 01 hingga 09 dan dari 10 hingga 12.
  • Hari "(0 [1-9] | 1 [0-9] | 2 [0-9] | 3 [0-2])". Dari 01 hingga 09 dan dari 10 hingga 19, dari 20 hingga 29 dan dari 30 hingga 32.
  • Jam "(0 [0-9] | 1 [0-9] | 2 [0-3])". Dari pukul 00 hingga 09 dan dari 10 hingga 19, dari 20 hingga 23.
  • Menit "([0-5] [\ d])". 00 hingga 59
  • (: ([0-5] [\ d]))? - detik opsional, dari 00 hingga 59.

Tugas 4 - cetak miring


http://callumacrae.imtqy.com/regex-tuesday/challenge4.html


Ada teks dengan markup MarkDown (seperti pada Habré). Anda harus menulis ekspresi reguler yang akan menggantikan kata-kata di antara tanda bintang dengan tag <em>.


Contoh


 *This text is italic.* -> <em>This text is italic.</em> 

Petunjuk

Anda harus menemukan tanda bintang sebelum dan sesudahnya tidak ada tanda bintang lain. Ada yang hanya melihat ke depan dan melihat ke depan dan ke belakang (yang paling sederhana, tetapi tidak lintas-browser.)


Solusi

Ekspresi:


 /(^|[^*])\*([^*].*?[^*]|[^*])\*((?!\*)|$)/g 

Penggantian:


 $1<em>$2</em> 

Solusi parsing
  • "(^ | [^ *])" - kita akan mulai dari awal baris, atau dari karakter apa pun kecuali tanda bintang. Grup perlu menangkap simbol ini dan meletakkannya di depan tag <em>.
  • ((?! *) | $) - kita akan mengakhiri dengan akhir baris, atau dengan karakter apa pun kecuali tanda bintang, karena di sini mengintip - ruang tidak ditangkap.
  • "([^ *]. *? [^ *] | [^ *])" - di tengah kita memiliki "[^ *]. *? [^ *]" Setiap teks yang tidak boleh dimulai dan diakhiri dengan tanda bintang dan ekspresi atau "| [^ *]" hanya untuk memperhitungkan satu karakter di dalam tag (tidak perlu lulus ujian).

Tugas 5 - Format Angka


http://callumacrae.imtqy.com/regex-tuesday/challenge5.html


Dari daftar angka, pilih hanya angka dengan format yang benar. Secara umum diterima untuk menulis angka dari kanan ke kiri, dipecah menjadi kelompok tiga digit di masing-masing.


Contoh angka yang direkam dengan benar:


 1,024 8,205,500.4672 10.444444444444 30 000,7302 

Petunjuk

Penting untuk mempertimbangkan bahwa angka-angka ditulis tepat dari kanan ke kiri, dan bukan sebaliknya. Ini berarti bahwa angka dapat dimulai dengan 1-3 digit, dan kemudian hanya ada tiga digit dalam grup. Di bagian non-integer bisa ada angka sebanyak yang Anda inginkan (atau tidak sama sekali). Mempertimbangkan bahwa pemisah grup dapat berupa koma atau spasi, dan pemisah bagian integer dan non-integer dapat berupa koma atau titik.


Solusi

Ekspresi:


 /^\d{1,3}([ ,]\d{3})*([.,]\d+)?$/ 

Solusi parsing
  • "^ \ d {1,3}" - di awal 1 hingga 3 digit.
  • "([,] \ d {3}) *" - selanjutnya sebuah pemisah dan sekelompok 3 angka, tanda bintang menunjukkan bahwa format kami dapat muncul 0 atau berkali-kali.
  • "([.,] \ d +)? $" - pada akhirnya adalah grup dengan pemisah dan angka, tanda tanya adalah penjumlah yang mengatakan bahwa kehadiran bagian non-integer bukanlah prasyarat.

Tugas 6 - alamat ip


http://callumacrae.imtqy.com/regex-tuesday/challenge6.html


Dari daftar alamat ip dalam berbagai format, temukan alamat ip yang valid. Mungkin tugas yang paling suram dari semua. Tidak terlalu rumit, seberapa suram.


Contoh entri dan penjelasan alamat IP yang valid:


  • 192.0.2.235 - desimal dengan titik.
  • 0300.0000.0002.0353 - oktal dengan titik-titik.
  • 0xC0.0x00.0x02.0xEB - heksadesimal dengan titik-titik.
  • 0xC00002EC - heksadesimal.
  • 287454020 - desimal
  • 030000001353 - oktal.

Mencampur format yang berbeda itu buruk. Terutama angkanya. Situasi ini semakin rumit oleh fakta bahwa format alamat ip dengan titik-titik dapat dicampur, misalnya - 0xFF.255.0377.0x12. Secara pribadi, pendapat saya adalah bahwa ini adalah praktik yang buruk, namun demikian, menurut pengujian, opsi tersebut dimungkinkan dan karenanya ini harus diperhitungkan.


Petunjuk
  • 192.0.2.235 - desimal dengan titik. Notasi umum dapat dinyatakan dari 1 hingga 3 digit antara titik (nilai dari 0 hingga 255).
  • 0300.0000.0002.0353 - oktal dengan titik-titik. 4 digit antara titik dengan nilai dari 0 hingga 7.
  • 0xC0.0x00.0x02.0xEB - heksadesimal dengan titik-titik. Empat karakter di antara titik-titik. Memimpin "0x", lalu dua karakter (dengan digit atau dari "a" ke "f").
  • 0xC00002EC - heksadesimal. Memimpin "0x", lalu 8 karakter (nilai digit atau dari "a" ke "f").
  • 287454020 - desimal Angka dalam kisaran 0 hingga 4294967295.
  • 030000001353 - oktal. Leading 0. Angka-angka tersebut dari 0 hingga 7. Kisarannya adalah 0 hingga 0777777777777777.

Ekspresi reguler akan sangat bagus.


Solusi
 /^((((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])|(0x[\da-f]{2})|([0-7]{4}))\.){3}(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])|(0x[\da-f]{2})|([0-7]{4})))|(0x[\da-f]{8})|(0([0-7]{1,11}))|(2874540[2-8][0-9]|28745409[0-9]|287454[1-9][0-9]{2}|28745[5-9][0-9]{3}|2874[6-9][0-9]{4}|287[5-9][0-9]{5}|28[89][0-9]{6}|29[0-9]{7}|[3-9][0-9]{8}|[1-3][0-9]{9}|4[01][0-9]{8}|42[0-8][0-9]{7}|429[0-3][0-9]{6}|4294[0-8][0-9]{5}|42949[0-5][0-9]{4}|429496[0-6][0-9]{3}|4294967[01][0-9]{2}|42949672[0-8][0-9]|429496729[0-5]))$/i 

Solusi parsing

Untuk alamat-ip dengan titik-titik, pencampuran dimungkinkan, jadi kami menulis opsi melalui "|" dengan pola seperti itu: ((desimal | heksadesimal | oktal).) {3} (desimal | heksadesimal | oktal).


  • "(\ d | [1-9] \ d | 1 \ d \ d | 2 [0-4] \ d | 25 [0-5])" - untuk desimal dengan titik catatan.
  • "(0x [\ da-f] {2})" - untuk heksadesimal dengan titik rekaman.
  • "([0-7] {4})" - untuk oktal dengan titik rekor.

Dan format rekaman lainnya:


  • "(0x [\ da-f] {8})" - untuk notasi heksadesimal.
  • "(2874540 [2-8] [0-9] | 28745409 [0-9] | 287454 [1-9] [0-9] [0-9] {2} | 28745 [5-9] [0-9] {3} | 2874 [6-9] [0-9] {4} | 287 [5-9] [0-9] {5} | 28 [89] [0-9] {6} | 29 [0-9] {7} | [3-9] [0-9] {8} | [1-3] [0-9] {9} | 4 [01] [0-9] {8} | 42 [0-8 ] [0-9] {7} | 429 [0-3] [0-9] {6} | 4294 [0-8] [0-9] {5} | 42949 [0-5] [0-9 ] {4} | 429496 [0-6] [0-9] {3} | 4294967 [01] [0-9] {2} | 42949672 [0-8] [0-9] | 429496729 [0-5 ]) "- untuk notasi desimal. Dan di sini, saya harus mengakui, untuk ekspresi yang lebih pendek, saya curang dengan memasukkan hanya alamat IP desimal dalam rentang pengujian. Demi kebaikan, di sini Anda perlu mempertimbangkan angka dari 0 hingga 4294967295. Untuk menulis ini secara manual bukanlah tugas yang bersyukur, jadi kami menggunakannya .
  • (0 ([0-7] {1,11})) - untuk notasi oktal.

Tugas 7 - url


http://callumacrae.imtqy.com/regex-tuesday/challenge7.html


Dari daftar url, temukan valid.


Contoh alamat yang valid:


 http://ab https://example.com/ http://test.this-test.com/ http://1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa 

Petunjuk

Alamat tersebut harus dimulai di http: // atau https: //, dan diakhiri dengan garis miring, huruf (jika domain), atau angka jika alamat ip. Setiap domain dapat memiliki subdomain. Menurut standar, panjang setiap domain tidak boleh melebihi 63 karakter dengan total panjang 255 karakter . Domain yang bersarang di subdomain terbatas hingga 127 domain . Sayangnya, mesin JavaScript Regex tidak akan sepenuhnya mengaktifkan pembatasan ini, tetapi Anda dapat menulis ekspresi yang secara kasar akan mematuhi aturan dan lulus tes. Coret apa yang bisa dielakkan dengan menyesuaikan parameter lainnya.


Solusi
 /^https?:\/\/(((\b[az\d-]{1,63}\b)\.){1,40}(\b[az\d-]{1,63}\b))\/?$/i 

Solusi parsing
  • "^ https ?: \ / \ /" - http: // atau https: //

Mari kita analisa secara terpisah ((\ b [az \ d -] {1,63} \ b).) {1,40}


  • "\ b" di akhir dan awal domain untuk memastikan bahwa domain tidak memulai dan tidak diakhiri dengan sesuatu yang tidak valid.
  • "[az \ d -] {1,63}" - di dalam huruf nama domain, angka dan tanda hubung diizinkan di dalam
  • "{1.63}" - semua ini tidak lebih dari 63 karakter.
  • "((nama-domain).) {1,40}" - Saya ingin memasukkan 127 di sini, tetapi dalam ekspresi reguler, kuantifier {,} berarti interval pengulangan. Dalam hal menggunakan [] {} - ini adalah jumlah karakter, tetapi dalam kasus tanpa [] - ini persis jumlah pengulangan templat (nama-domain).). Oleh karena itu, kami membatasi pengulangan hingga 40 agar tidak melebihi batas panjang umum, yang kami juga, karena alasan ini, tidak dapat diatur secara ketat.

Tugas 8 - Elemen Berulang


http://callumacrae.imtqy.com/regex-tuesday/challenge8.html


Tugas ini sangat mirip dengan tugas 1 dalam banyak hal, tetapi di sini Anda perlu menemukan dan menyoroti elemen berulang dari daftar MarkDown dengan dua tanda bintang.


Daftar seperti itu:


 * Repeated list item * Repeated list item 

Harus dikonversi ke ini:


 * Repeated list item * **Repeated list item** 

Petunjuk

Kami menggunakan tautan balik, karakter umpan baris, global, multi-line, dan kunci tidak sensitif.


Solusi

Ekspresi:


 /^(\*\s+([^\n]+)\n\*\s+)(\2)$/gmi 

Penggantian:


 $1**$3** 

Tugas 9 - MarkDown Links


http://callumacrae.imtqy.com/regex-tuesday/challenge9.html


Ganti tautan MarkDown yang valid dengan tautan html.


Contoh Konversi:


 [Another](http://example.com/) -> <a href="http://example.com/">Another</a> 

Petunjuk

Itu bisa dilakukan tanpa mengintip sama sekali, atau dengan hanya melihat ke depan. Alih-alih melihat ke belakang, itu adalah pengganti.


Solusi

Ekspresi:


 /(^|\s+)\[([^\]\[]+)\]\s*\((https?:\/\/\b[az\d-]+\b(\.[az-]+)*\.\w+\/*)\)(?=$|\s+)/i 

Penggantian:


 $1<a href="$3">$2</a> 

Solusi parsing
  • "(^ | \ s +)" - sebelum tautan MarkDown, baik awal garis atau spasi diizinkan. Kami membawa ini ke grup untuk menggantikan ruang yang diambil dengan mengganti $ 1.
  • "[([^] [] +)] \ s *" - karakter apa pun selain tanda kutip diperbolehkan di header.
  • "(https ?: \ / \ / \ b [az \ d -] + \ b (. [az -] +) . \ w + \ / )" - kami memeriksa bahwa alamat url valid.
  • "(? = $ | \ s +)" - di akhir spasi atau di akhir baris.

Tugas 10 - Kata Kunci


http://callumacrae.imtqy.com/regex-tuesday/challenge10.html


Tantangan paling sulit dari semuanya. Menggunakan ekspresi reguler dengan penggantian, ubah teks yang ada menjadi kata kunci yang dipisahkan oleh koma.


Aturan:


  • Tanda kutip adalah satu kata kunci.
  • Nama yang ditulis dgn tanda penghubung adalah satu kata kunci.
  • Kata itu mungkin mengandung tanda kutip.
  • Simbol (; - '") harus dihapus.

Contohnya adalah ini:


jangan beri tahu Suzie Smith-Hopper bahwa saya melanggar mainan kuda Daniel


Harus dikonversi ke ini:


jangan, katakan, Suzie, Smith-Hopper, bahwa, aku, bangkrut, mainan Daniel, kuda


Sekilas tidak terdengar rumit, tetapi tidak. Faktanya adalah bahwa masalah seperti itu tidak diselesaikan dan tidak dibawa ke bentuk akhir dengan hanya satu ekspresi reguler dengan penggantinya. Tetapi test case dirancang sedemikian rupa sehingga semuanya memungkinkan solusi untuk masalah tersebut.


Petunjuk

Penting untuk memutuskan di mana menempatkan koma, apa yang harus diganti di sebelah koma ini dan di sisi mana. Ada asumsi dalam masalah - kata pertama dalam setiap kasus uji tidak memerlukan perubahan apa pun. Ini berarti Anda harus meletakkan koma di sebelah kiri kata yang diganti, kecuali kata pertama.


Solusi

Ekspresi:


 /\s(['"])([^'"]+)\1|(;? |['"]? | ['"]|-{2,})(\w+)/g 

Penggantian:


 ,$2$4 

Solusi parsing

Karena kami telah memutuskan tempat untuk meletakkan koma, kami akan memutuskan apa yang akan kami ganti dengan koma ini dan apa yang akan dihapus.


  • "\ s (['"]) ([^' "] +)" - ganti templat {spasi "kata dengan spasi dalam tanda kutip"} oleh {, kata-kata dengan spasi} . "\" di sini bukan hanya seperti itu, tetapi untuk mengecualikan kejadian palsu dengan kutipan yang salah ditempatkan.
  • "(;? | ['"]? | [' "] | - {2,}) (\ w +)" - maka ada kata tunggal yang didahului oleh karakter yang perlu dihapus, dan koma sebelum kata-kata ini.

Source: https://habr.com/ru/post/id474184/


All Articles