Contoh ekspresi reguler jquery. Pertandingan dan grup. Menerapkan ekspresi reguler ke string

Regex atau ekspresi reguler menakutkan bagi pemula, tetapi penting bagi programmer mana pun. Mari kita pahami ekspresi reguler di 5 contoh sederhana dengan JavaScript.

Jika Anda mempunyai masalah dan ingin menyelesaikannya dengan ekspresi reguler, Anda sekarang mempunyai dua masalah. Ada pepatah. Ekspresi reguler yang ditemukan dalam kode terkadang menimbulkan ketakutan dan kebencian pada orang yang tidak mengenalnya.

Namun kenyataannya, regex apa pun hanyalah ekspresi templat yang dapat menyelesaikan masalah seluruh fungsi dalam satu baris. Namun, untuk membuat ekspresi reguler, Anda perlu mempertimbangkan serangkaian aturan ketat yang dapat membuat pemula bingung dan membuat kesalahan.

Karakter yang cocok

Ekspresi reguler paling dasar adalah ekspresi yang cocok dengan karakter tunggal. Berikut aturan mereka:

1. Tanda titik (.) cocok dengan karakter apa pun. Jika Anda perlu mencari titik tertentu, Anda harus menghindarinya menggunakan karakter “\” (\.).

2. Tanda tanya (?) menunjukkan bahwa karakter sebelumnya bersifat opsional. Untuk mencari tanda tanya itu sendiri dalam sebuah string, ia juga harus di-escape dengan "\" (\?).

var text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit lest. Donec convallis dignissim ligula, et rutrum est elat vistibulum eu."; // "elit" dan "elat" bisa digunakan. Titik berarti simbol apa pun bisa digunakan. var regex = /el.t/g; console.log(text.match(regex)); // "est" dan "lest" akan bekerja dengan baik. Tanda tanya menjadikan "l" opsional. var regex2 = /l?est/g; console.log(text.match(regex2));

var teks = "Lorem ipsum dolor sit amet, consectetur adipiscing elite jangan sampai. Donec convallis dignissim ligula, et rutrum est elat vistibulum eu.";

// Baik "elit" maupun "elat" bisa digunakan. Titik berarti simbol apa pun bisa digunakan.

var regex = /el.t/g ;

menghibur. log(text.match(regex));

// "est" dan "lest" akan bekerja dengan baik. Tanda tanya menjadikan "l" opsional.

var regex2 = /l?est/g ;

menghibur. log(text.match(regex2));

Cocokkan banyak karakter

Himpunan adalah satu atau lebih karakter yang diapit tanda kurung, misalnya . Ekspresi seperti itu hanya akan mencari kumpulan karakter ini dalam sebuah string - in dalam contoh ini hanya a, b atau c. Sebaliknya, Anda dapat mencari kemunculan simbol apa pun kecuali menggunakan simbol “^”. [^abc] akan cocok dengan karakter apa pun selain a, b, atau c. Anda juga dapat menentukan rentang karakter atau angka, misalnya , .

Ada kumpulan karakter bawaan yang memudahkan penulisan ekspresi reguler. Mereka disebut singkatan atau steno. Misalnya, Anda dapat menulis \D saja. Terdapat singkatan untuk karakter lain (termasuk angka dan garis bawah) - \w dan \W, serta spasi - \s dan \S.

// Hanya "cat" dan "can" yang bisa digunakan, bukan "car". var text = "kaleng mobil kucing"; console.log(text.match(/ca/g)); // Semuanya akan lolos kecuali cat dan can (ada simbol ^) console.log(text.match(/ca[^tn]/g)); // Contoh lain di mana hanya angka yang lolos text = "Saya ingin 8 cangkir kopi."; console.log("Berapa cangkir: " + text.match(//g)); // Cara yang lebih mudah menggunakan pintasan \d console.log("Berapa banyak cangkir: " + text.match(/\d/g)); // Melewati semuanya kecuali angka console.log(text.match(/\D/g));

// Hanya "cat" dan "can" yang bisa digunakan, bukan "car".

var text = "kaleng mobil kucing" ;

menghibur. log(text.match(/ca/g));

// Melewati semuanya kecuali cat dan can (ada simbol ^)

menghibur. log (teks .cocok (/ca[^tn]/g ) ) ;

// Contoh lain di mana hanya angka saja yang lolos

teks = "Saya ingin 8 cangkir kopi.";

menghibur. log("Berapa cangkir: " + teks .cocok (//g ) ) ;

// Cara yang lebih mudah menggunakan pintasan \d

menghibur. log("Berapa cangkir: " + text .match (/\d/g ) ) ;

// Semuanya akan berlalu kecuali angka

menghibur. log(text.match(/\D/g));

Kata-kata yang cocok

Dalam kebanyakan kasus, Anda perlu mencari seluruh kata, bukan karakter individu. Hal ini dilakukan dengan menggunakan pengubah (+) dan (-), yang mengulangi karakter atau kumpulan karakter.

Menambahkan (X) menentukan jumlah pasti pengulangan, (x, y) – rentang (x dan y adalah angka).

Selain itu, ada pola khusus \b yang mencocokkan batas di akhir kata.

var text = "Halo orang-orang tahun 1974. Saya datang dari masa depan. Pada tahun 2014 kita memiliki senjata laser, papan layang, dan kehidupan di bulan!"; // Akan menemukan tahun. \d+ akan cocok dengan satu atau lebih karakter var yearRegex = /\d+/g; console.log("Tahun: ", text.match(tahunRegex)); // Menemukan semua kalimat. Kalimat kita diawali dengan huruf kapital dan diakhiri dengan tanda titik atau tanda seru. var kalimatRegex = /.+?(\.|!)/g; console.log("Kalimat: ", text.match(sentenceRegex)); // Menemukan semua kata yang dimulai dengan "h". Baik huruf besar maupun huruf kecil cocok untuk kita, jadi kita menggunakan pengubah i // \b untuk mendefinisikan batas kata. var hKata = /\bh\w+/ig; console.log("H Kata: ", text.match(hWords)); // Menemukan semua kata dari 4 hingga 6 karakter var findWords = /\b\w(4,6)\b/g; console.log("Kata-kata antara 4 dan 6 karakter: ", text.match(findWords)); // Temukan kata yang panjangnya lebih dari 5 karakter console.log("Kata dengan panjang 5 karakter atau lebih: ", text.match(/\b\w(5,)\b/g)); // Menemukan kata yang panjangnya persis 6 karakter console.log("Kata-kata yang panjangnya persis 6 karakter: ", text.match(/\b\w(6)\b/g));

var teks = "Halo orang-orang tahun 1974. Saya datang dari masa depan. Pada tahun 2014 kita memiliki senjata laser, papan layang, dan hidup di bulan!";

// Akan menemukan tahun. \d+ cocok dengan satu atau lebih karakter

var tahunRegex = /\d+/g ;

menghibur. log("Tahun:", teks.cocok (tahunRegex));

// Menemukan semua kalimat. Kalimat kita diawali dengan huruf kapital dan diakhiri dengan tanda titik atau tanda seru.

var kalimatRegex = /.+?(\.|!)/g ;

menghibur. log("Kalimat: ", text.match(sentenceRegex));

// Menemukan semua kata yang dimulai dengan "h". Baik huruf besar maupun huruf kecil cocok untuk kami, jadi kami menggunakan pengubah i

// \b untuk menentukan batasan kata.

var hKata = /\bh\w+/i g ;

menghibur. log("H Kata: ",teks.cocok(hWords));

// Menemukan semua kata dari 4 hingga 6 karakter

var findWords = /\b\w(4,6)\b/g ;

menghibur. catatan( "Kata-kata antara 4 dan 6 karakter:", teks. cocok (menemukan Kata-kata));

// Temukan kata yang panjangnya lebih dari 5 karakter

menghibur. log ("Kata-kata 5 karakter atau lebih panjang: " , text .match (/\b\w(5,)\b/g ) ) ;

// Temukan kata yang panjangnya persis 6 karakter

menghibur. catatan( "Kata-kata panjangnya persis 6 karakter:", teks. cocok (/\b\w(6)\b/g ) ) ;

Validasi seluruh string

Dalam JavaScript, ekspresi seperti itu dapat digunakan untuk memvalidasi input pengguna dari kolom teks. Untuk memvalidasi string, ekspresi reguler reguler digunakan, diikat ke awal dan akhir fragmen teks, menggunakan ekspresi ^ (awal baris) dan $ (akhir baris) untuk tujuan ini. Simbol-simbol ini memastikan bahwa pola yang Anda tulis mencakup keseluruhan teks, bukan hanya mencocokkan sebagian saja.

Selain itu, dalam kasus ini, kami menggunakan metode test() dari objek regex, yang mengembalikan nilai benar atau salah saat menguji apakah ekspresi reguler cocok dengan string.

// Kita mempunyai serangkaian string, ayo cari tautan..com/", "123461", "https://site/?s=google", "http://bukan url yang valid", "abc http: / /invalid.url/" ]; var regex = /^https?:\/\/[\w\/?.&-=]+$/; var urls = ; for(var i = 0; i< strings.length; i++){ if(regex.test(strings[i])){ // Валидная ссылка urls.push(strings[i]); } } console.log("Valid URLs: ", urls);

// Kita mempunyai serangkaian string, mari kita cari tautannya.

var string = [

"https://situs/" ,

"ini bukan URL",

"https://google.com/",

"123461" ,

"https://situs/?s=google" ,

"http://bukan url yang valid",

"abc http://invalid.url/"

var regex = / ^ https ? : \ / \ / [ \ w \ / ? . & -= ] + $ / ;

var url = ;

untuk (var saya = 0 ; saya< strings . length ; i ++ ) {

if (regex .test (string [ i ] ) ) (

url. mendorong(string[i]);

menghibur. log("URL yang valid: ",url);

Cari dan ganti

Tugas umum lainnya yang menjadi lebih mudah dengan menggunakan ekspresi reguler adalah menemukan dan mengganti teks.

Ekspresi Reguler

Ekspresi reguler adalah objek yang menggambarkan pola karakter. Kelas RegExp dalam JavaScript mewakili ekspresi reguler, dan objek kelas String dan RegExp menentukan metode yang menggunakan ekspresi reguler untuk melakukan pencocokan pola serta operasi pencarian dan penggantian teks. Tata bahasa ekspresi reguler JavaScript berisi subset yang cukup lengkap dari sintaksis ekspresi reguler yang digunakan di Perl 5, jadi jika Anda memiliki pengalaman dengan Perl, Anda dapat dengan mudah menulis pola dalam program JavaScript.

Fitur ekspresi reguler Perl yang tidak didukung di ECMAScript mencakup tanda s (mode satu baris) dan x (sintaks diperluas); escape sequence \a, \e, \l, \u, \L, \U, \E, \Q, \A, \Z, \z dan \G serta konstruksi lanjutan lainnya yang dimulai dengan (?.

Mendefinisikan Ekspresi Reguler

DI DALAM JavaScript biasa ekspresi diwakili oleh objek RegExp. Objek RegExp dapat dibuat menggunakan konstruktor RegExp(), namun lebih sering objek tersebut dibuat menggunakan sintaks literal khusus. Sama seperti literal string yang ditentukan sebagai karakter yang dikelilingi oleh tanda kutip, literal ekspresi reguler ditentukan sebagai karakter yang diapit oleh sepasang karakter garis miring (/). Jadi kode JavaScript Anda mungkin berisi baris seperti ini:

Pola var = /s$/;

Baris ini membuat objek RegExp baru dan menugaskannya ke variabel pola. Objek RegExp ini mencari string apa pun yang diakhiri dengan karakter "s". Ekspresi reguler yang sama dapat didefinisikan menggunakan konstruktor RegExp():

Pola var = RegExp baru("s$");

Spesifikasi pola ekspresi reguler terdiri dari urutan karakter. Kebanyakan karakter, termasuk semua karakter alfanumerik, secara harfiah menggambarkan karakter yang harus ada. Artinya, ekspresi reguler /java/ cocok dengan semua baris yang mengandung substring “java”.

Karakter lain dalam ekspresi reguler tidak dimaksudkan untuk digunakan untuk menemukan padanan persisnya, melainkan memiliki arti khusus. Misalnya, ekspresi reguler /s$/ berisi dua karakter. Karakter pertama s menunjukkan pencarian karakter literal. Kedua, $ adalah metakarakter khusus yang menandai akhir sebuah baris. Jadi ekspresi reguler ini cocok dengan string apa pun yang diakhiri dengan karakter s.

Bagian berikut menjelaskan berbagai karakter dan metakarakter yang digunakan dalam ekspresi reguler di JavaScript.

Karakter literal

Seperti disebutkan sebelumnya, semua karakter alfabet dan angka dalam ekspresi reguler cocok dengan dirinya sendiri. Sintaks ekspresi reguler dalam JavaScript juga mendukung kemampuan untuk menentukan karakter non-abjad tertentu menggunakan urutan escape yang dimulai dengan karakter garis miring terbalik (\). Misalnya, urutan \n cocok dengan karakter baris baru. Simbol-simbol tersebut tercantum dalam tabel di bawah ini:

Beberapa tanda baca memiliki arti khusus dalam ekspresi reguler:

^ $ . * + ? = ! : | \ / () { } -

Arti dari simbol-simbol ini dijelaskan pada bagian berikut. Beberapa di antaranya mempunyai arti khusus hanya dalam konteks ekspresi reguler tertentu, sedangkan dalam konteks lain ditafsirkan secara harfiah. Namun, secara umum, untuk memasukkan salah satu karakter ini ke dalam ekspresi reguler, Anda harus mengawalinya dengan karakter garis miring terbalik. Karakter lain, seperti tanda kutip dan @, tidak memiliki arti khusus dan hanya cocok dengan ekspresi regulernya.

Jika Anda tidak dapat mengingat dengan tepat karakter mana yang harus diawali dengan \, Anda dapat dengan aman memberi tanda garis miring terbalik di depan karakter mana pun. Namun, perlu diingat bahwa banyak huruf dan angka memiliki arti khusus jika digabungkan dengan karakter garis miring, jadi huruf dan angka yang sebenarnya Anda cari tidak boleh diawali dengan karakter \. Untuk menyertakan karakter garis miring terbalik itu sendiri dalam ekspresi reguler, Anda harus terlebih dahulu mengawalinya dengan karakter garis miring terbalik lainnya. Misalnya, ekspresi reguler berikut cocok dengan string apa pun yang berisi karakter garis miring terbalik: /\\/.

Kelas karakter

Karakter literal individu dapat digabungkan menjadi kelas karakter dengan mengapitnya dalam tanda kurung siku. Kelas karakter cocok dengan karakter apa pun yang ada di kelas itu. Oleh karena itu, ekspresi reguler // cocok dengan salah satu karakter a, b, atau c.

Kelas karakter negatif juga dapat didefinisikan untuk mencocokkan karakter apa pun kecuali yang ditentukan dalam tanda kurung. Kelas karakter negasi ditentukan oleh karakter ^ sebagai karakter pertama setelah tanda kurung kiri. Ekspresi reguler /[^abc]/ cocok dengan karakter apa pun selain a, b, atau c. Di kelas karakter, serangkaian karakter dapat ditentukan menggunakan tanda hubung. Semua karakter Latin huruf kecil ditemukan menggunakan ekspresi //, dan huruf atau angka apa pun dari kumpulan karakter Latin dapat ditemukan menggunakan ekspresi //.

Kelas karakter tertentu sangat umum, jadi sintaksis ekspresi reguler di JavaScript menyertakan karakter khusus dan rangkaian escape untuk mewakilinya. Jadi, \s cocok dengan spasi, tab, dan karakter spasi putih Unicode apa pun, dan \S cocok dengan karakter spasi putih non-Unicode apa pun.

Tabel di bawah ini menyediakan daftar karakter khusus dan sintaksis kelas karakter. (Perhatikan bahwa beberapa rangkaian escape kelas karakter hanya cocok dengan karakter ASCII dan tidak diperluas untuk berfungsi dengan karakter Unicode. Anda dapat secara eksplisit menentukan kelas karakter Unicode Anda sendiri, misalnya /[\u0400-\u04FF]/ cocok dengan karakter apa pun alfabet Sirilik .)

Kelas Karakter Ekspresi Reguler JavaScript
Simbol Korespondensi
[...] Salah satu karakter yang ditampilkan dalam tanda kurung
[^...] Salah satu karakter yang tidak tercantum dalam tanda kurung
. Karakter apa pun selain baris baru atau pembatas baris Unicode lainnya
\w Karakter teks ASCII apa pun. Setara
\W Karakter apa pun yang bukan karakter teks ASCII. Setara dengan [^a-zA-Z0-9_]
\S Karakter spasi putih apa pun dari kumpulan Unicode
\S Karakter apa pun yang bukan spasi dari kumpulan Unicode. Harap dicatat bahwa karakter \w dan \S bukanlah hal yang sama
\D Nomor ASCII apa pun. Setara
\D Karakter apa pun selain angka ASCII. Setara dengan [^0-9]
[\B] Karakter spasi mundur literal

Perhatikan urutan escape tersebut karakter khusus kelas mungkin dalam tanda kurung siku. \s cocok dengan karakter spasi apa pun dan \d cocok dengan digit apa pun, maka /[\s\d]/ cocok dengan karakter atau digit spasi apa pun.

Pengulangan

Mengingat pengetahuan tentang sintaksis ekspresi reguler yang diperoleh sejauh ini, kita dapat mendeskripsikan angka dua digit sebagai /\d\d/ atau angka empat digit sebagai /\d\d\d\d/, tetapi kita tidak bisa, misalnya , mendeskripsikan angka yang terdiri dari sejumlah digit, atau rangkaian tiga huruf diikuti dengan digit opsional. Pola yang lebih kompleks ini menggunakan sintaksis ekspresi reguler, yang menentukan berapa kali elemen ekspresi reguler tertentu dapat diulang.

Simbol berulang selalu mengikuti pola penerapannya. Beberapa jenis pengulangan cukup sering digunakan, dan tersedia simbol khusus untuk menunjukkan kasus ini. Misalnya, + cocok dengan satu atau lebih contoh pola sebelumnya. Tabel berikut memberikan ringkasan sintaks pengulangan:

Baris berikut menunjukkan beberapa contoh:

Pola var = /\d(2,4)/; // Mencocokkan angka yang berisi dua hingga empat digit pola = /\w(3)\d?/; // Mencocokkan tepat tiga karakter kata dan satu pola digit opsional = /\s+java\s+/; // Mencocokkan kata "java" dengan satu spasi atau lebih // sebelum dan sesudahnya pola = /[^(]*/; // Mencocokkan dengan nol atau lebih karakter selain tanda kurung pembuka

Hati-hati saat menggunakan karakter pengulangan * dan ?. Mereka dapat mencocokkan ketiadaan pola yang ditentukan sebelumnya dan oleh karena itu ketiadaan karakter. Misalnya, ekspresi reguler /a*/ cocok dengan string "bbbb" karena tidak mengandung karakter a.

Karakter pengulangan yang tercantum dalam tabel mewakili jumlah pengulangan maksimum yang memungkinkan bagian berikutnya dari ekspresi reguler dicocokkan. Kami mengatakan ini adalah pengulangan yang serakah. Dimungkinkan juga untuk menerapkan pengulangan yang dilakukan dengan cara yang tidak serakah. Cukup dengan menunjukkan pengulangan setelah simbol (atau simbol). tanda tanya: ??, +?, *? atau bahkan (1,5)?.

Misalnya, ekspresi reguler /a+/ cocok dengan satu atau lebih contoh huruf a. Diterapkan pada string "aaa", cocok dengan ketiga huruf tersebut. Di sisi lain, ekspresi /a+?/ cocok dengan satu atau lebih contoh huruf a dan memilih yang paling sedikit mungkin jumlah karakter. Diterapkan pada string yang sama, pola ini hanya cocok dengan huruf pertama a.

Pengulangan yang “tidak serakah” tidak selalu memberikan hasil yang diharapkan. Pertimbangkan pola /a+b/, yang cocok dengan satu atau lebih a yang diikuti oleh a b. Ketika diterapkan pada string "aaab", itu sesuai dengan keseluruhan string.

Sekarang mari kita periksa versi "tidak serakah" dari /a+?b/. Orang mungkin berpikir bahwa itu akan cocok dengan a b yang didahului oleh hanya satu a. Jika diterapkan pada string yang sama, "aaab" diharapkan cocok dengan karakter tunggal a dan karakter terakhir b. Namun, pola ini sebenarnya cocok dengan keseluruhan string, sama seperti versi serakah. Faktanya adalah bahwa pencarian pola ekspresi reguler dilakukan dengan menemukan posisi pertama dalam string, mulai dari mana kecocokan menjadi mungkin. Karena kecocokan dimungkinkan dimulai dari karakter pertama string, kecocokan lebih pendek yang dimulai dari karakter berikutnya bahkan tidak dipertimbangkan.

Alternatif, Pengelompokan dan Tautan

Tata bahasa ekspresi reguler mencakup karakter khusus untuk menentukan alternatif, mengelompokkan subekspresi, dan referensi ke subekspresi sebelumnya. Simbol pipa | berfungsi untuk memisahkan alternatif. Misalnya, /ab|cd|ef/ cocok dengan string "ab", atau string "cd", atau string "ef", dan pola /\d(3)|(4)/ cocok dengan tiga digit atau empat huruf kecil.

Perhatikan bahwa alternatif diproses dari kiri ke kanan hingga ditemukan kecocokan. Jika ditemukan kecocokan dengan alternatif kiri, maka alternatif kanan akan diabaikan, bahkan jika kecocokan yang “lebih baik” dapat dicapai. Jadi ketika pola /a|ab/ diterapkan pada string "ab", itu hanya akan cocok dengan karakter pertama.

Tanda kurung memiliki banyak arti dalam ekspresi reguler. Salah satunya adalah pengelompokan elemen individu menjadi satu subekspresi, sehingga elemennya bila menggunakan karakter khusus |, *, +, ? dan lainnya dianggap sebagai satu kesatuan. Misalnya, pola /java(script)?/ cocok dengan kata "java" diikuti dengan kata opsional "script", dan /(ab|cd)+|ef)/ cocok dengan string "ef" atau satu atau lebih pengulangan salah satu dari string "ab" atau "cd".

Penggunaan lain dari tanda kurung dalam ekspresi reguler adalah untuk mendefinisikan subpola dalam suatu pola. Ketika kecocokan ekspresi reguler ditemukan dalam string target, bagian dari string target yang cocok dengan subpola tertentu yang diapit tanda kurung dapat diekstraksi.

Misalkan Anda ingin mencari satu atau lebih huruf kecil yang diikuti oleh satu atau lebih angka. Untuk melakukan ini, Anda dapat menggunakan templat /+\d+/. Tapi mari kita asumsikan juga bahwa kita hanya menginginkan angka di akhir setiap pertandingan. Jika kita menempatkan bagian pola ini dalam tanda kurung (/+(\d+)/), kita dapat mengekstrak angka dari setiap kecocokan yang kita temukan. Cara melakukannya akan dijelaskan di bawah.

Penggunaan subekspresi dalam tanda kurung yang terkait adalah merujuk pada subekspresi dari bagian sebelumnya dari ekspresi reguler yang sama. Hal ini dicapai dengan menentukan satu atau lebih digit setelah karakter \. Angka-angka tersebut mengacu pada posisi subekspresi yang diberi tanda kurung dalam ekspresi reguler. Misalnya, \1 mengacu pada subekspresi pertama, dan \3 merujuk pada subekspresi ketiga. Perhatikan bahwa subekspresi dapat disarangkan satu sama lain, sehingga posisi tanda kurung kiri digunakan saat menghitung. Misalnya, dalam ekspresi reguler berikut, referensi subekspresi bertumpuk (cript) akan terlihat seperti \2:

/(ava(cript)?)\sis\s(menyenangkan\w*)/

Referensi ke subekspresi sebelumnya tidak menunjuk pada pola subekspresi tersebut, namun pada teks yang ditemukan yang cocok dengan pola tersebut. Oleh karena itu, referensi dapat digunakan untuk menerapkan batasan yang memilih bagian string yang berisi karakter yang persis sama. Misalnya, ekspresi reguler berikut cocok dengan nol atau lebih karakter di dalam tanda kutip tunggal atau ganda. Namun, tanda kutip pembuka dan penutup tidak harus cocok satu sama lain (yaitu, kedua tanda kutip harus tunggal atau ganda):

/[""][^""]*[""]/

Kita dapat meminta tanda kutip untuk dicocokkan menggunakan referensi seperti ini:

Di sini \1 cocok dengan subekspresi pertama. Dalam contoh ini, tautan menerapkan batasan yang mengharuskan tanda kutip penutup cocok dengan tanda kutip pembuka. Ekspresi reguler ini tidak mengizinkan tanda kutip tunggal di dalam tanda kutip ganda, dan sebaliknya.

Dimungkinkan juga untuk mengelompokkan elemen dalam ekspresi reguler tanpa membuat referensi bernomor ke elemen tersebut. Daripada sekadar mengelompokkan elemen di antara ( dan ), mulailah grup dengan simbol (?: dan akhiri dengan simbol). Misalnya saja pola berikut ini:

/(ava(?:cript)?)\sis\s(menyenangkan\w*)/

Disini subekspresi (?:cript) hanya diperlukan untuk pengelompokan agar karakter pengulangan ? Tanda kurung yang dimodifikasi ini tidak membuat tautan, jadi dalam ekspresi reguler ini, \2 mengacu pada teks yang cocok dengan polanya (menyenangkan\w*).

Tabel berikut mencantumkan operator pemilihan, pengelompokan, dan referensi dalam ekspresi reguler:

Pemilihan JavaScript, pengelompokan, dan tautan simbol ekspresi reguler
Simbol Arti
| Alternatif. Cocok dengan subekspresi di sebelah kiri atau subekspresi di sebelah kanan.
(...) Pengelompokan. Mengelompokkan elemen menjadi satu kesatuan yang dapat digunakan dengan karakter *, +, ?, | dll. Juga mengingat karakter yang cocok dengan grup ini untuk digunakan dalam referensi berikutnya.
(?:...) Hanya pengelompokan. Mengelompokkan elemen menjadi satu unit, tetapi tidak mengingat karakter yang sesuai dengan grup ini.
\nomor Cocok dengan karakter yang sama yang ditemukan saat mencocokkan nomor nomor grup. Grup adalah subekspresi di dalam tanda kurung (mungkin bersarang). Nomor kelompok ditentukan dengan menghitung tanda kurung kiri dari kiri ke kanan. Grup yang dibentuk dengan menggunakan simbol (?:) tidak diberi nomor.

Menentukan Posisi Pertandingan

Seperti dijelaskan sebelumnya, banyak elemen ekspresi reguler yang cocok dengan satu karakter dalam string. Misalnya, \s cocok dengan satu karakter spasi. Elemen ekspresi reguler lainnya cocok dengan posisi antar karakter, bukan karakter itu sendiri. Misalnya, \b cocok dengan batas kata—batas antara \w (karakter teks ASCII) dan \W (karakter non-teks), atau batas antara karakter teks ASCII dan awal atau akhir baris.

Elemen seperti \b tidak menentukan karakter apa pun yang harus ada dalam string yang cocok, namun menentukan posisi valid untuk pencocokan. Elemen-elemen ini terkadang disebut elemen jangkar ekspresi reguler karena mereka mengaitkan pola ke posisi tertentu dalam string. Elemen jangkar yang paling umum digunakan adalah ^ dan $, yang masing-masing menghubungkan pola ke awal dan akhir garis.

Misalnya, kata "JavaScript" pada barisnya sendiri dapat ditemukan menggunakan ekspresi reguler /^JavaScript$/. Untuk menemukan kata terpisah"Java" (bukan awalan, seperti pada kata "JavaScript"), Anda dapat mencoba menggunakan pola /\sJava\s/, yang memerlukan spasi sebelum dan sesudah kata.

Namun solusi seperti itu menimbulkan dua masalah. Pertama, ia hanya akan menemukan kata "Java" jika dikelilingi oleh spasi di kedua sisinya, dan tidak akan dapat menemukannya di awal atau akhir baris. Kedua, ketika pola ini cocok, string yang dikembalikan akan berisi spasi di awal dan akhir, yang tidak persis seperti yang kita inginkan. Jadi daripada menggunakan pola yang cocok dengan karakter spasi \s, kita akan menggunakan pola (atau jangkar) yang cocok dengan batas kata \b. Hasilnya adalah ekspresi berikut: /\bJava\b/.

Elemen jangkar \B cocok dengan posisi yang bukan merupakan batas kata. Artinya, pola /\Bcript/ akan cocok dengan kata “JavaScript” dan “postscript” dan tidak akan cocok dengan kata “script” atau “Scripting”.

Ekspresi reguler yang sewenang-wenang juga dapat berfungsi sebagai kondisi jangkar. Jika Anda menempatkan ekspresi di antara karakter (?= dan), itu menjadi pengujian pencocokan maju terhadap karakter berikutnya, yang mengharuskan karakter tersebut cocok dengan pola yang ditentukan tetapi tidak disertakan dalam string pencocokan.

Misalnya, untuk mencocokkan nama bahasa pemrograman umum yang diikuti dengan titik dua, Anda dapat menggunakan ekspresi /ava(cript)?(?=\:)/. Pola ini cocok dengan kata "JavaScript" dalam string "JavaScript: The Definitive Guide", namun tidak akan cocok dengan kata "Java" dalam string "Java in a Nutshell" karena tidak diikuti oleh titik dua.

Jika Anda memasukkan kondisi (?!), maka ini akan menjadi pemeriksaan maju negatif untuk karakter berikutnya, yang mengharuskan karakter berikut tidak cocok dengan pola yang ditentukan. )/ cocok dengan substring “Java”, diikuti oleh huruf kapital dan sejumlah karakter teks ASCII, asalkan substring "Java" tidak diikuti oleh substring "Script". Ini akan cocok dengan string "JavaBeans" tetapi tidak dengan string "Javanese", dan akan cocok dengan string "JavaScrip" tetapi tidak dengan string "JavaScript" atau "JavaScripter".

Tabel di bawah ini menyediakan daftar karakter jangkar ekspresi reguler:

Karakter jangkar ekspresi reguler
Simbol Arti
^ Cocok dengan awal ekspresi string atau awal baris dalam pencarian multibaris.
$ Cocok dengan akhir ekspresi string atau akhir baris dalam pencarian multibaris.
\B Cocok dengan batas kata, mis. cocok dengan posisi antara karakter \w dan karakter \W, atau antara karakter \w dan awal atau akhir baris. (Namun, perlu diperhatikan bahwa [\b] cocok dengan karakter spasi mundur.)
\B Cocok dengan posisi yang bukan merupakan batasan kata.
(?=p) Pemeriksaan pandangan ke depan yang positif untuk karakter selanjutnya. Membutuhkan karakter berikutnya untuk mencocokkan pola p, tetapi tidak menyertakan karakter tersebut dalam string yang cocok.
(?!P) Pemeriksaan maju negatif untuk karakter berikutnya. Mengharuskan karakter berikut tidak cocok dengan pola p.

Bendera

Dan satu elemen terakhir dari tata bahasa ekspresi reguler. Bendera ekspresi reguler menentukan aturan pencocokan pola tingkat tinggi. Berbeda dengan tata bahasa ekspresi reguler lainnya, tanda tidak ditentukan di antara karakter garis miring, tetapi setelah karakter kedua. JavaScript mendukung tiga tanda.

Bendera saya menetapkan bahwa pencocokan pola harus peka huruf besar-kecil, dan bendera g- bahwa pencarian harus bersifat global, mis. semua kecocokan dalam string harus ditemukan. Bendera m melakukan pencarian pola dalam mode multi-baris. Jika ekspresi string yang dicari berisi baris baru, maka dalam mode ini karakter jangkar ^ dan $, selain mencocokkan awal dan akhir seluruh ekspresi string, juga mencocokkan awal dan akhir masing-masing baris. rangkaian teks. Misalnya, pola /java$/im cocok dengan “java” dan “Java\nis fun”.

Bendera ini dapat digabungkan dalam kombinasi apa pun. Misalnya, untuk mencari kemunculan pertama kata "java" (atau "Java", "JAVA", dll.) dengan cara yang tidak peka huruf besar-kecil, Anda dapat menggunakan ekspresi reguler yang tidak membedakan huruf besar-kecil /\bjava\b/ Saya. Dan untuk menemukan semua kemunculan kata ini dalam sebuah string, Anda dapat menambahkan flag g: /\bjava\b/gi.

Metode kelas String untuk mencari berdasarkan pola

Hingga saat ini, kita telah membahas tata bahasa dari ekspresi reguler yang kita buat, namun kita belum melihat bagaimana ekspresi reguler tersebut sebenarnya dapat digunakan dalam skrip JavaScript. DI DALAM bagian ini Kita akan membahas metode objek String yang menggunakan ekspresi reguler untuk pencocokan pola dan pencarian dengan penggantian. Dan kemudian kita akan melanjutkan percakapan kita tentang pencocokan pola dengan ekspresi reguler dengan melihat objek RegExp serta metode dan propertinya.

Strings mendukung empat metode menggunakan ekspresi reguler. Yang paling sederhana adalah metodenya mencari(). Dibutuhkan ekspresi reguler sebagai argumen dan mengembalikan posisi karakter pertama dari substring yang cocok, atau -1 jika tidak ditemukan kecocokan. Misalnya, panggilan berikut akan menghasilkan 4:

Var hasil = "JavaScript".pencarian(/script/i); // 4

Jika argumen pada metode search() bukan ekspresi reguler, argumen tersebut terlebih dahulu dikonversi dengan meneruskannya ke konstruktor RegExp. Metode search() tidak mendukung pencarian global dan mengabaikan tanda g dalam argumennya.

Metode mengganti() melakukan operasi pencarian dan penggantian. Dibutuhkan ekspresi reguler sebagai argumen pertama dan string pengganti sebagai argumen kedua. Metode ini mencari baris yang dipanggil untuk mencocokkan pola yang ditentukan.

Jika ekspresi reguler berisi tanda g, metode replace() akan menggantikan semua kecocokan yang ditemukan dengan string pengganti. Jika tidak, ini hanya akan menggantikan kecocokan pertama yang ditemukan. Jika argumen pertama metode replace() adalah string dan bukan ekspresi reguler, maka metode akan melakukan penelusuran literal untuk string tersebut, bukan mengonversinya menjadi ekspresi reguler menggunakan konstruktor RegExp() seperti yang dilakukan metode search().

Sebagai contoh, kita dapat menggunakan metode replace() untuk menggunakan huruf besar pada kata "JavaScript" secara konsisten di seluruh baris teks:

// Terlepas dari huruf besar/kecil karakternya, kami menggantinya dengan kata jika diperlukan var result = "javascript".replace(/JavaScript/ig, "JavaScript");

Metode replace() lebih dari itu alat yang ampuh daripada yang disarankan oleh contoh ini. Izinkan saya mengingatkan Anda bahwa subekspresi dalam tanda kurung dalam ekspresi reguler diberi nomor dari kiri ke kanan, dan ekspresi reguler tersebut mengingat teks yang terkait dengan setiap subekspresi. Jika string pengganti berisi tanda $ diikuti dengan angka, metode replace() akan menggantikan kedua karakter tersebut dengan teks yang cocok dengan subekspresi yang ditentukan. Ini sangat peluang yang berguna. Kita dapat menggunakannya, misalnya, untuk mengganti tanda kutip lurus dalam sebuah string dengan tanda kutip tipografi, yang disimulasikan oleh karakter ASCII:

// Kutipan adalah kutipan yang diikuti oleh sejumlah karakter // selain tanda kutip (yang kita ingat), diikuti oleh kutipan lain // var quote = /"([^"]*)"/g; // Ganti tanda kutip lurus dengan tipografi dan membiarkan "$1" tidak berubah // isi kutipan disimpan dalam $1 var text = ""JavaScript" adalah bahasa pemrograman yang ditafsirkan."; var result = text.replace(quote, ""$1"" ) ; // "JavaScript" adalah bahasa pemrograman yang ditafsirkan.

Hal penting yang perlu diperhatikan adalah argumen kedua pada replace() dapat berupa fungsi yang menghitung string pengganti secara dinamis.

Metode cocok()- ini adalah metode yang paling umum kelas String menggunakan ekspresi reguler. Dibutuhkan ekspresi reguler sebagai satu-satunya argumennya (atau mengonversi argumennya menjadi ekspresi reguler dengan meneruskannya ke konstruktor RegExp()) dan mengembalikan array yang berisi hasil pencarian. Jika tanda g diatur dalam ekspresi reguler, metode akan mengembalikan array yang berisi semua kecocokan yang ada dalam string. Misalnya:

// akan mengembalikan ["1", "2", "3"] var result = "1 ditambah 2 sama dengan 3".match(/\d+/g);

Jika ekspresi reguler tidak berisi tanda g, metode match() tidak melakukan pencarian global; itu hanya mencari pertandingan pertama. Namun, match() mengembalikan array bahkan ketika metode tersebut tidak melakukan pencarian global. Dalam hal ini, elemen pertama array adalah substring yang ditemukan, dan semua elemen sisanya adalah subekspresi dari ekspresi reguler. Oleh karena itu, jika match() mengembalikan array arr, maka arr akan berisi seluruh string yang ditemukan, arr substring yang sesuai dengan subekspresi pertama, dll. Menggambar paralel dengan metode replace(), kita dapat mengatakan bahwa isi $n dimasukkan ke dalam arr[n].

Misalnya saja lihat berikut ini kode program yang mem-parsing URL:

Var url = /(\w+):\/\/([\w.]+)\/(\S*)/; var text = "Kunjungi situs web kami http://www..php"; var hasil = teks.pertandingan(url); if (hasil != null) ( var fullurl = hasil; // Berisi "http://www..php" var protokol = hasil; // Berisi "http" var host = hasil; // Berisi "www..php " )

Perlu dicatat bahwa untuk ekspresi reguler yang tidak memiliki tanda g yang disetel pencarian global, metode match() mengembalikan nilai yang sama dengan metode exec() ekspresi reguler: array yang dikembalikan memiliki properti indeks dan input, seperti yang dijelaskan dalam pembahasan metode exec() di bawah.

Metode objek String terakhir yang menggunakan ekspresi reguler adalah membelah(). Metode ini membagi string yang dipanggil menjadi array substring, menggunakan argumen sebagai pembatas. Misalnya:

"123.456.789".split(","); // Kembalikan ["123","456","789"]

Metode split() juga dapat menggunakan ekspresi reguler sebagai argumen. Hal ini membuat metode ini lebih ampuh. Misalnya, Anda dapat menentukan pembatas yang mengizinkan sejumlah karakter spasi di kedua sisi:

"1, 2, 3 , 4 , 5".split(/\s*,\s*/); // Kembalikan ["1","2","3","4","5"]

objek RegExp

Seperti disebutkan, ekspresi reguler direpresentasikan sebagai objek RegExp. Selain konstruktor RegExp(), objek RegExp mendukung tiga metode dan beberapa properti.

Konstruktor RegExp() mengambil satu atau dua argumen string dan membuat objek RegExp baru. Argumen pertama ke konstruktor adalah string yang berisi isi ekspresi reguler, mis. teks yang harus muncul di antara karakter garis miring dalam literal ekspresi reguler. Perhatikan bahwa literal string dan ekspresi reguler menggunakan karakter \ untuk merepresentasikan rangkaian escape, jadi ketika meneruskan ekspresi reguler sebagai literal string ke konstruktor RegExp(), Anda harus mengganti setiap karakter \ dengan sepasang karakter \\.

Argumen kedua pada RegExp() mungkin hilang. Jika ditentukan, ini mendefinisikan tanda ekspresi reguler. Harus salah satu karakter g, i, m, atau kombinasi dari karakter tersebut. Misalnya:

// Menemukan semua angka lima digit dalam sebuah string. Catatan // penggunaan simbol dalam contoh ini \\ var zipcode = new RegExp("\\d(5)", "g");

Konstruktor RegExp() berguna ketika ekspresi reguler dihasilkan secara dinamis dan oleh karena itu tidak dapat direpresentasikan menggunakan sintaks literal ekspresi reguler. Misalnya, untuk menemukan string yang dimasukkan oleh pengguna, Anda perlu membuat ekspresi reguler saat runtime menggunakan RegExp().

Properti RegExp

Setiap objek RegExp memiliki lima properti. Milik sumber- string read-only yang berisi teks ekspresi reguler. Milik global adalah nilai boolean read-only yang menentukan apakah flag g ada dalam ekspresi reguler. Milik abaikan Kasus adalah nilai boolean read-only yang menentukan apakah flag i ada dalam ekspresi reguler. Milik multiline adalah nilai boolean read-only yang menentukan apakah flag m ada dalam ekspresi reguler. Dan properti terakhir indeks terakhir adalah bilangan bulat yang dapat dibaca dan ditulis. Untuk pola dengan bendera g, properti ini berisi nomor posisi pada baris di mana pencarian berikutnya harus dimulai. Seperti dijelaskan di bawah, ini digunakan oleh metode exec() dan test().

Metode RegExp

Objek RegExp mendefinisikan dua metode yang melakukan pencocokan pola; mereka berperilaku serupa dengan metode kelas String yang dijelaskan di atas. Metode utama kelas RegExp yang digunakan untuk pencocokan pola adalah eksekutif(). Ini mirip dengan metode match() kelas String yang disebutkan di atas, kecuali bahwa ini adalah metode kelas RegExp yang menggunakan string sebagai argumen, bukan metode kelas String yang menggunakan argumen RegExp.

Metode exec() mengeksekusi ekspresi reguler untuk string yang ditentukan, yaitu. mencari kecocokan dalam sebuah string. Jika tidak ditemukan kecocokan, metode akan mengembalikan null. Namun, jika kecocokan ditemukan, ia akan mengembalikan array yang sama dengan array yang dikembalikan oleh metode match() untuk pencarian tanpa tanda g. Elemen nol Array berisi string yang cocok dengan ekspresi reguler, dan semua elemen berikutnya adalah substring yang cocok dengan semua subekspresi. Selain itu, properti indeks berisi nomor posisi karakter yang memulai fragmen terkait, dan properti masukan mengacu pada baris yang dicari.

Berbeda dengan match(), metode exec() mengembalikan array yang strukturnya tidak bergantung pada keberadaan flag g dalam ekspresi reguler. Izinkan saya mengingatkan Anda bahwa ketika meneruskan ekspresi reguler global, metode match() mengembalikan array kecocokan yang ditemukan. Dan exec() selalu mengembalikan satu kecocokan, tetapi memberikan informasi tentangnya informasi lengkap. Saat exec() dipanggil pada ekspresi reguler yang berisi tanda g, metode ini akan menyetel properti lastIndex objek ekspresi reguler ke nomor posisi karakter tepat setelah substring yang ditemukan.

Ketika exec() dipanggil untuk kedua kalinya pada ekspresi reguler yang sama, ia memulai pencarian pada karakter yang posisinya ditentukan dalam properti lastIndex. Jika exec() tidak menemukan kecocokan, properti lastIndex disetel ke 0. (Anda juga dapat menyetel lastIndex ke nol kapan saja, yang harus dilakukan jika pencarian berakhir sebelum kecocokan terakhir dalam satu baris adalah ditemukan, dan pencarian dimulai pada baris lain dengan objek RegExp yang sama.) Perilaku khusus ini memungkinkan exec() dipanggil berulang kali untuk mengulangi semua kecocokan ekspresi reguler di baris tersebut. Misalnya:

Pola var = /Java/g; var text = "JavaScript lebih dari itu hal yang lucu daripada Java!"; var hasil; while((hasil = pola.exec(teks)) != null) ( console.log("Ditemukan "" + hasil + """ + " pada posisi " + hasil.index + " ; pencarian selanjutnya akan dimulai dari " + pattern.lastIndex);

Metode lain dari objek RegExp adalah tes(), itu banyak metode yang lebih sederhana eksekutif(). Dibutuhkan string dan mengembalikan nilai true jika string cocok dengan ekspresi reguler:

Pola var = /java/i; pola.test("JavaScript"); // Mengembalikan nilai benar

Memanggil test() sama dengan memanggil exec(), yang mengembalikan nilai true jika exec() mengembalikan sesuatu selain null. Karena alasan ini, metode test() berperilaku sama seperti metode exec() ketika dipanggil pada ekspresi reguler global: metode ini mulai mencari string tertentu pada posisi yang ditentukan oleh properti lastIndex, dan jika menemukan kecocokan , setel properti lastIndex ke nomor posisi karakter tepat di sebelah kecocokan yang ditemukan. Oleh karena itu, dengan menggunakan metode test(), Anda dapat membuat loop traversal garis dengan cara yang sama seperti menggunakan metode exec().

Beberapa orang, ketika dihadapkan pada suatu masalah, berpikir: “Oh, saya akan menggunakan ekspresi reguler.” Sekarang mereka punya dua masalah.
Jamie Zawinski

Yuan-Ma berkata, “Dibutuhkan banyak tenaga untuk memotong kayu melintasi serat kayu. Dibutuhkan banyak kode untuk memprogram seluruh struktur masalah.
Master Yuan-Ma, “Buku Pemrograman”

Alat dan teknik pemrograman bertahan dan menyebar secara evolusioner dan kacau. Kadang-kadang bukan orang-orang cantik dan cemerlang yang bisa bertahan, tapi mereka yang bekerja cukup baik di bidangnya - misalnya, jika mereka diintegrasikan ke dalam teknologi sukses lainnya.

Dalam bab ini, kita akan membahas alat seperti itu - ekspresi reguler. Ini adalah cara untuk mendeskripsikan pola dalam data string. Mereka membuat bahasa kecil yang berdiri sendiri yang disertakan dalam JavaScript dan banyak bahasa serta alat lainnya.

Jadwal rutinnya sangat aneh dan sangat berguna. Sintaksnya samar dan antarmuka pemrograman JavaScript-nya kikuk. Tapi ini adalah alat yang ampuh untuk mengeksplorasi dan memanipulasi string. Setelah Anda memahaminya, Anda akan menjadi programmer yang lebih efektif.

Membuat ekspresi reguler

Reguler – tipe objek. Itu dapat dibuat dengan memanggil konstruktor RegExp, atau dengan menulis template yang diinginkan, diapit oleh garis miring.

Var re1 = RegExp baru("abc"); var re2 = /abc/;

Kedua ekspresi reguler ini mewakili pola yang sama: karakter “a” diikuti oleh karakter “b” diikuti oleh karakter “c”.

Jika Anda menggunakan konstruktor RegExp maka polanya ditulis sebagai tali biasa, jadi semua aturan mengenai garis miring terbalik berlaku.

Entri kedua, yang polanya berada di antara garis miring, menangani garis miring terbalik secara berbeda. Pertama, karena polanya diakhiri dengan garis miring, kita perlu meletakkan garis miring terbalik sebelum garis miring yang ingin kita sertakan dalam pola kita. Selain itu, garis miring terbalik yang bukan bagian dari karakter khusus seperti \n akan dipertahankan (daripada diabaikan seperti pada string), dan akan mengubah arti polanya. Beberapa karakter, seperti tanda tanya atau plus, memiliki arti khusus dalam ekspresi reguler, dan jika perlu mencari karakter seperti itu, karakter tersebut juga harus diawali dengan garis miring terbalik.

Var delapan belasPlus = /delapan belas\+/;

Untuk mengetahui karakter mana yang perlu diawali dengan garis miring, Anda perlu mempelajari daftar semua karakter khusus dalam ekspresi reguler. Hal ini belum bisa dilakukan, jadi jika ragu, cukup beri tanda garis miring terbalik di depan karakter apa pun yang bukan huruf, angka, atau spasi.

Memeriksa kecocokan

Regular memiliki beberapa metode. Yang paling sederhana adalah tes. Jika Anda meneruskannya sebuah string, ia akan mengembalikan nilai Boolean yang menunjukkan apakah string tersebut berisi kemunculan pola yang diberikan.

Console.log(/abc/.test("abcde")); // → true console.log(/abc/.test("abxde")); // → salah

Urutan reguler yang hanya terdiri dari karakter non-khusus hanyalah urutan karakter tersebut. Jika abc berada di mana saja pada baris yang kita uji (tidak hanya di awal), pengujian akan menghasilkan nilai true.

Mencari sekumpulan karakter

Anda juga bisa mengetahui apakah suatu string berisi abc menggunakan indexOf. Pola teratur memungkinkan Anda melangkah lebih jauh dan membuat pola yang lebih kompleks.

Katakanlah kita perlu mencari nomor apa pun. Saat kita meletakkan sekumpulan karakter dalam tanda kurung siku pada ekspresi reguler, artinya bagian ekspresi tersebut cocok dengan salah satu karakter dalam tanda kurung.

Kedua ekspresi tersebut berada dalam baris yang berisi angka.

Console.log(//.test("pada tahun 1992")); // → true console.log(//.test("pada tahun 1992")); // → benar

Dalam tanda kurung siku, tanda hubung antara dua karakter digunakan untuk menentukan rentang karakter, yang urutannya ditentukan oleh pengkodean Unicode. Karakter dari 0 hingga 9 hanya ada dalam satu baris (kode dari 48 hingga 57), sehingga karakter tersebut menangkap semuanya dan mencocokkan nomor apa pun.

Beberapa kelompok karakter mempunyai singkatan tersendiri.

\d Nomor berapa saja
\w Karakter alfanumerik
\s Karakter spasi putih (spasi, tab, baris baru, dll.)
\D bukan angka
\W bukan karakter alfanumerik
\S bukan karakter spasi
. karakter apa pun kecuali umpan baris

Dengan demikian, Anda dapat mengatur format tanggal dan waktu seperti 30/01/2003 15:20 dengan ekspresi berikut:

Var tanggalWaktu = /\d\d-\d\d-\d\d\d\d \d\d:\d\d/; console.log(dateTime.test("30-01-2003 15:20")); // → true console.log(dateTime.test("30-Jan-2003 15:20")); // → salah

Terlihat mengerikan, bukan? Terlalu banyak garis miring terbalik, sehingga polanya sulit dipahami. Kami akan memperbaikinya sedikit nanti.

Garis miring terbalik juga dapat digunakan dalam tanda kurung siku. Misalnya, [\d.] berarti angka atau titik apa pun. Perhatikan bahwa periode di dalam tanda kurung siku kehilangan arti khususnya dan hanya menjadi sebuah periode. Hal yang sama berlaku untuk karakter khusus lainnya, seperti +.

Anda dapat membalikkan sekumpulan karakter - yaitu, katakanlah Anda perlu mencari karakter apa pun kecuali karakter yang ada dalam kumpulan tersebut - dengan menempatkan tanda ^ tepat setelah tanda kurung siku pembuka.

Var notBinary = /[^01]/; console.log(notBinary.test("1100100010100110")); // → false console.log(notBinary.test("1100100010200110")); // → benar

Mengulangi bagian template

Kami tahu cara menemukan satu nomor. Bagaimana jika kita perlu mencari bilangan bulat - barisan satu atau lebih digit?

Jika Anda memberi tanda + setelah sesuatu dalam urutan yang benar, ini berarti elemen tersebut dapat diulang lebih dari satu kali. /\d+/ berarti satu atau lebih digit.

Console.log(/"\d+"/.test(""123"")); // → true console.log(/"\d+"/.test("""")); // → false console.log(/"\d*"/.test(""123"")); // → true console.log(/"\d*"/.test("""")); // → benar

Tanda bintang * mempunyai arti yang hampir sama, namun memungkinkan pola muncul sebanyak nol kali. Jika sesuatu diikuti oleh tanda bintang, maka hal itu tidak pernah menghalangi pola untuk berada dalam garis - hanya muncul di sana nol kali.

Tanda tanya membuat bagian dari pola menjadi opsional, artinya dapat muncul nol atau satu kali. Dalam contoh berikut, karakter u mungkin muncul, namun polanya cocok meskipun tidak.

Var tetangga = /tetangga?r/; console.log(neighbor.test("neighbor")); // → true console.log(neighbor.test("neighbor")); // → benar

Kurung kurawal digunakan untuk menentukan berapa kali suatu pola harus muncul. (4) setelah suatu elemen berarti harus muncul 4 kali dalam satu baris. Anda juga dapat menentukan celah: (2,4) berarti elemen tersebut harus muncul minimal 2 dan tidak lebih dari 4 kali.

Versi lain dari format tanggal dan waktu, di mana hari, bulan, dan jam diperbolehkan satu atau dua digit. Dan itu juga sedikit lebih mudah dibaca.

Var tanggalWaktu = /\d(1,2)-\d(1,2)-\d(4) \d(1,2):\d(2)/; console.log(dateTime.test("30-1-2003 8:45")); // → benar

Anda dapat menggunakan ruang terbuka dengan menghilangkan salah satu nomornya. (,5,) berarti pola tersebut dapat muncul dari nol hingga lima kali, dan (5,) berarti lima kali atau lebih.

Mengelompokkan Subekspresi

Untuk menggunakan operator * atau + pada beberapa elemen sekaligus, Anda dapat menggunakan tanda kurung. Bagian dari ekspresi reguler yang diapit tanda kurung dianggap sebagai salah satu elemen dari sudut pandang operator.

Var kartunMenangis = /boo+(hoo+)+/i; console.log(cartoonCrying.test("Boohoooohoohooo")); // → benar

Tanda plus pertama dan kedua hanya berlaku untuk huruf o kedua dalam boo dan hoo. + ketiga mengacu pada keseluruhan grup (hoo+), menemukan satu atau lebih urutan tersebut.

Huruf i di akhir ekspresi membuat ekspresi reguler tidak peka huruf besar-kecil - sehingga B cocok dengan b.

Pertandingan dan Grup

Metode pengujian adalah metode paling sederhana untuk memeriksa ekspresi reguler. Ini hanya memberi tahu Anda apakah kecocokan ditemukan atau tidak. Regular juga memiliki metode exec, yang akan mengembalikan null jika tidak ada yang ditemukan, dan sebaliknya mengembalikan objek dengan informasi tentang kecocokan.

Var pertandingan = /\d+/.exec("satu dua 100"); console.log(cocok); // → ["100"] console.log(match.index); // → 8

Objek yang dikembalikan oleh exec memiliki properti indeks, yang berisi jumlah karakter asal kecocokan. Secara umum, objek terlihat seperti array string, dimana elemen pertama adalah string yang diperiksa kecocokannya. Dalam contoh kita, ini adalah urutan angka yang kita cari.

String memiliki metode pencocokan yang bekerja dengan cara yang hampir sama.

Console.log("satu dua 100".cocok(/\d+/)); // → ["100"]

Jika ekspresi reguler berisi subekspresi yang dikelompokkan berdasarkan tanda kurung, teks yang cocok dengan grup ini juga akan muncul dalam array. Elemen pertama selalu merupakan kecocokan yang lengkap. Bagian kedua adalah bagian yang cocok dengan kelompok pertama (yang tanda kurungnya muncul lebih dulu), kemudian kelompok kedua, dan seterusnya.

Var quoteText = /"([^"]*)"/; console.log(quotedText.exec("dia berkata "halo"")); // → [""halo"", "halo"]

Jika suatu grup tidak ditemukan sama sekali (misalnya, jika diikuti dengan tanda tanya), posisinya dalam larik tidak ditentukan. Jika sebuah grup cocok beberapa kali, maka hanya pertandingan terakhir yang akan ada dalam array.

Console.log(/bad(ly)?/.exec("bad")); // → ["buruk", tidak terdefinisi] console.log(/(\d)+/.exec("123")); // → ["123", "3"]

Grup berguna untuk mengambil bagian dari string. Jika kita tidak hanya ingin memeriksa apakah suatu string memiliki tanggal, tetapi mengekstraknya dan membuat objek yang mewakili tanggal tersebut, kita dapat menyertakan urutan angka dalam tanda kurung dan memilih tanggal dari hasil exec.

Tapi pertama-tama, sedikit penyimpangan di mana kita akan mempelajari cara yang lebih disukai untuk menyimpan tanggal dan waktu dalam JavaScript.

Jenis tanggal

JavaScript punya tipe standar objek untuk tanggal - atau lebih tepatnya, momen dalam waktu. Namanya Tanggal. Jika Anda hanya membuat objek tanggal menggunakan yang baru, Anda akan mendapatkan tanggal dan waktu saat ini.

Console.log(Tanggal baru()); // → Minggu 09 Nov 2014 00:07:57 GMT+0300 (CET)

Anda juga dapat membuat objek yang berisi waktu tertentu

Console.log(Tanggal baru(2015, 9, 21)); // → Rabu 21 Okt 2015 00:00:00 GMT+0300 (CET) console.log(Tanggal baru(2009, 11, 9, 12, 59, 59, 999)); // → Rabu 09 Des 2009 12:59:59 GMT+0300 (CET)

JavaScript menggunakan konvensi di mana angka bulan dimulai dengan angka nol dan angka hari dimulai dengan angka satu. Ini bodoh dan konyol. Hati-Hati.

Empat argumen terakhir (jam, menit, detik, dan milidetik) bersifat opsional dan disetel ke nol jika tidak ada.

Stempel waktu disimpan sebagai jumlah milidetik yang telah berlalu sejak awal tahun 1970. Untuk masa sebelum tahun 1970, angka negatif digunakan (hal ini disebabkan oleh konvensi waktu Unix yang dibuat sekitar waktu itu). Metode getTime objek tanggal mengembalikan nomor ini. Tentu saja ukurannya besar.
console.log(Tanggal baru(2013, 11, 19).getTime()); // → 1387407600000 console.log(Tanggal baru(1387407600000)); // → Kam 19 Des 2013 00:00:00 GMT+0100 (CET)

Jika Anda memberikan satu argumen kepada konstruktor Tanggal, argumen tersebut akan diperlakukan sebagai jumlah milidetik ini. Anda bisa mendapatkan nilai milidetik saat ini dengan membuat objek Date dan memanggil metode getTime, atau dengan memanggil fungsi Date.now.

Objek Tanggal memiliki metode getFullYear, getMonth, getDate, getHours, getMinutes, dan getSeconds untuk mengambil komponennya. Ada juga metode getYear yang mengembalikan kode dua digit yang tidak berguna seperti 93 atau 14.

Dengan menyertakan bagian template yang relevan dalam tanda kurung, kita dapat membuat objek tanggal langsung dari string.

Fungsi findDate(string) ( var dateTime = /(\d(1,2))-(\d(1,2))-(\d(4))/; var match = dateTime.exec(string); return Tanggal baru(Nomor(pertandingan), Nomor(pertandingan) - 1, Nomor(pertandingan) ) console.log(findDate("30-1-2003")); // → Kam 30 Jan 2003 00:00:00 GMT+0100 (CET)

Batas kata dan garis

Sayangnya, findDate dengan senang hati akan mengekstrak tanggal tidak berarti 00-1-3000 dari string "100-1-30000". Kecocokan bisa terjadi di mana saja dalam string, jadi dalam hal ini itu hanya akan dimulai dari karakter kedua dan berakhir pada karakter kedua hingga terakhir.

Jika kita perlu memaksa kecocokan untuk mengambil seluruh string, kita menggunakan tag ^ dan $. ^ cocok dengan awal baris, dan $ cocok dengan akhir. Oleh karena itu /^\d+$/ cocok dengan string yang hanya terdiri dari satu digit atau lebih, /^!/ cocok dengan string yang dimulai dengan tanda seru, dan /x^/ tidak cocok dengan baris mana pun (tidak boleh ada x sebelum awal baris).

Sebaliknya, jika kita hanya ingin memastikan bahwa tanggal dimulai dan diakhiri pada batas kata, kita menggunakan tanda \b. Batas kata dapat berupa awal atau akhir baris, atau tempat mana pun dalam baris yang terdapat karakter alfanumerik \w di satu sisi dan karakter non-alfanumerik di sisi lain.

Console.log(/cat/.test("menggabungkan")); // → true console.log(/\bcat\b/.test("concatenate")); // → salah

Perhatikan bahwa label batas bukanlah sebuah simbol. Ini hanyalah sebuah batasan yang berarti kecocokan hanya terjadi jika kondisi tertentu terpenuhi.

Templat dengan pilihan

Katakanlah Anda perlu mencari tahu apakah teks tersebut tidak hanya berisi angka, tetapi angka yang diikuti oleh babi, sapi, atau ayam dalam bentuk tunggal atau jamak.

Dimungkinkan untuk menulis tiga ekspresi reguler dan memeriksanya satu per satu, tetapi ada cara yang lebih baik. Simbol | menunjukkan pilihan antara pola di kiri dan kanannya. Dan kami dapat mengatakan yang berikut:

Var animalCount = /\b\d+ (babi|sapi|ayam)s?\b/; console.log(animalCount.test("15 babi")); // → true console.log(animalCount.test("15 ekor babi")); // → salah

Tanda kurung membatasi bagian pola yang | diterapkan, dan banyak operator seperti itu dapat ditempatkan satu demi satu untuk menunjukkan pilihan dari lebih dari dua opsi.

Mesin Pencari

Ekspresi reguler dapat dianggap sebagai diagram alur. Diagram berikut menjelaskan contoh peternakan terkini.

Suatu ekspresi cocok dengan string jika dimungkinkan untuk menemukan jalur dari sisi kiri diagram ke kanan. Kita ingat posisi saat ini dalam garis, dan setiap kali kita melewati persegi panjang, kita memeriksa apakah bagian garis tepat setelah posisi kita di dalamnya cocok dengan isi persegi panjang.

Ini berarti memeriksa apakah karakter reguler kita cocok dengan string “3 babi” saat menelusuri diagram alur akan terlihat seperti ini:

Di posisi 4 ada batas kata, dan kita melewati persegi panjang pertama
- mulai dari posisi ke-4 kita cari nomornya dan lewati persegi panjang kedua
- pada posisi 5, satu jalur menutup kembali di depan persegi panjang kedua, dan jalur kedua berlanjut lebih jauh ke persegi panjang yang diberi spasi. Kami memiliki spasi, bukan angka, dan kami memilih jalur kedua.
- sekarang kita berada di posisi 6, awal dari “babi”, dan di tiga percabangan jalan. Tidak ada “sapi” atau “ayam” di antrean, tapi ada “babi”, jadi kami memilih jalan ini.
- pada posisi 9 setelah pertigaan tiga kali lipat, satu jalur melewati "s" dan menuju ke persegi panjang batas kata terakhir, dan jalur kedua melewati "s". Kami memiliki huruf "s" jadi kami pergi ke sana.
- pada posisi 10 kita berada di ujung baris, dan hanya batas kata saja yang bisa cocok. Ujung garis dianggap sebagai batas, dan kita melewati persegi panjang terakhir. Dan sekarang kita telah berhasil menemukan template kita.

Pada dasarnya, cara kerja ekspresi reguler adalah algoritme dimulai dari awal string dan mencoba menemukan kecocokan di sana. Dalam kasus kita, ada batas kata, sehingga melewati persegi panjang pertama - tetapi tidak ada angka di sana, sehingga tersandung pada persegi panjang kedua. Kemudian berpindah ke karakter kedua dalam string, dan mencoba menemukan kecocokan di sana... Dan seterusnya hingga menemukan kecocokan atau mencapai akhir string, dalam hal ini tidak ditemukan kecocokan.

suap

Ekspresi reguler /\b(+b|\d+|[\da-f]h)\b/ cocok dengan bilangan biner yang diikuti oleh a b, bilangan desimal tanpa akhiran, atau bilangan heksadesimal (angka 0 hingga 9 atau simbol dari a sampai h), diikuti h. Diagram yang relevan:

Saat mencari kecocokan, mungkin saja algoritme mengambil jalur teratas (bilangan biner), meskipun tidak ada nomor tersebut dalam string. Jika ada garis “103”, misalnya, jelas baru setelah mencapai angka 3 algoritma akan memahami bahwa ia berada di jalur yang salah. Secara umum, garis tersebut cocok dengan urutan reguler, hanya saja tidak di thread ini.

Kemudian algoritme diputar kembali. Di pertigaan, ia mengingat posisi saat ini (dalam kasus kami, ini adalah awal baris, tepat setelah batas kata) sehingga Anda dapat kembali dan mencoba jalur lain jika jalur yang dipilih tidak berhasil. Untuk string “103”, setelah menemukan angka tiga, ia akan kembali dan mencoba melewati jalur desimal. Ini akan berhasil sehingga kecocokan akan ditemukan.

Algoritme berhenti segera setelah menemukan kecocokan yang lengkap. Artinya, meskipun beberapa opsi mungkin cocok, hanya satu opsi yang digunakan (sesuai urutan kemunculannya dalam urutan biasa).

Backtracking terjadi ketika menggunakan operator pengulangan seperti + dan *. Jika Anda mencari /^.*x/ di string "abcxe", bagian regex.* akan mencoba menggunakan seluruh string. Algoritme kemudian akan menyadari bahwa ia juga membutuhkan “x”. Karena tidak ada “x” setelah akhir string, algoritme akan mencoba mencari kecocokan dengan memundurkan satu karakter. Setelah abcx juga tidak ada x, lalu roll kembali lagi, kali ini ke substring abc. Dan setelah garis tersebut, ia menemukan x dan melaporkan kecocokan yang berhasil, di posisi 0 hingga 4.

Anda dapat menulis rutinitas rutin yang akan menyebabkan banyak kemunduran. Masalah ini terjadi ketika pola dapat mencocokkan data masukan beberapa kali. cara yang berbeda. Misalnya saja kita melakukan kesalahan saat menulis ekspresi reguler untuk bilangan biner, kita mungkin secara tidak sengaja menulis sesuatu seperti /(+)+b/.

Jika algoritme mencari pola seperti itu dalam string panjang 0 dan 1 yang tidak memiliki "b" di akhir, algoritme tersebut akan melewati loop dalam terlebih dahulu hingga kehabisan digit. Kemudian dia akan menyadari bahwa tidak ada "b" di akhir, dia akan memutar kembali satu posisi, melewati loop luar, menyerah lagi, mencoba memutar kembali ke posisi lain di sepanjang loop dalam... Dan dia akan melanjutkan untuk mencari dengan cara ini, menggunakan kedua loop. Artinya, jumlah pekerjaan dengan setiap karakter baris akan berlipat ganda. Bahkan untuk beberapa lusin karakter, menemukan kecocokan akan memakan waktu yang sangat lama.

ganti metode

String memiliki metode replace yang dapat mengganti sebagian string dengan string lain.

Console.log("ayah".replace("p", "m")); // → peta

Argumen pertama juga bisa berupa ekspresi reguler, dalam hal ini kemunculan pertama ekspresi reguler dalam baris akan diganti. Ketika opsi “g” (global) ditambahkan ke regex, semua kemunculan diganti, bukan hanya yang pertama

Console.log("Borobudur".replace(//, "a")); // → Barobudur console.log("Borobudur".replace(//g, "a")); // → Barabadar

Masuk akal untuk meneruskan opsi "ganti semua" melalui argumen terpisah, atau melalui metode terpisah seperti replaceAll. Namun sayangnya, opsi tersebut ditularkan melalui sistem reguler itu sendiri.

Kekuatan penuh dari ekspresi reguler terungkap ketika kita menggunakan tautan ke grup yang ditemukan dalam sebuah string, yang ditentukan dalam ekspresi reguler. Misalnya, kita mempunyai baris yang berisi nama orang, satu nama per baris, dalam format "Nama Belakang, Nama Depan". Jika kita perlu menukarnya dan menghapus koma untuk mendapatkan “Nama Depan Nama Belakang”, kita menulis yang berikut:

Console.log("Hopper, Grace\nMcCarthy, John\nRitchie, Dennis" .replace(/([\w ]+), ([\w ]+)/g, "$2 $1")); // → Grace Hopper // John McCarthy // Dennis Ritchie

$1 dan $2 pada baris pengganti mengacu pada kelompok karakter yang diapit tanda kurung. $1 diganti dengan teks yang cocok dengan grup pertama, $2 dengan grup kedua, dan seterusnya hingga $9. Keseluruhan kecocokan terkandung dalam variabel $&.

Anda juga bisa meneruskan fungsi sebagai argumen kedua. Untuk setiap penggantian, suatu fungsi akan dipanggil yang argumennya adalah grup yang ditemukan (dan seluruh bagian baris yang cocok), dan hasilnya akan dimasukkan ke dalam baris baru.

Contoh sederhana:

Var s = "cia dan fbi"; console.log(s.replace(/\b(fbi|cia)\b/g, function(str) ( return str.toUpperCase(); ))); // → CIA dan FBI

Ini yang lebih menarik:

Var stock = "1 buah lemon, 2 buah kubis, dan 101 butir telur"; function minusOne(match, amount, unit) ( amount = Number(amount) - 1; if (amount == 1) // hanya tersisa satu, hilangkan tanda "s" di akhir unit = unit.slice(0, unit. panjang - 1); else if (jumlah == 0) jumlah = "tidak"; jumlah yang dikembalikan + " " + unit; ) console.log(stock.replace(/(\d+) (\w+)/g, minusOne) ); // → tanpa lemon, 1 kubis, dan 100 butir telur

Kode mengambil sebuah string, menemukan semua kemunculan angka yang diikuti oleh sebuah kata, dan mengembalikan sebuah string dengan setiap angka dikurangi satu.

Grup (\d+) masuk ke argumen jumlah, dan (\w+) masuk ke argumen unit. Fungsi ini mengubah jumlah menjadi angka - dan ini selalu berhasil, karena pola kita adalah \d+. Dan kemudian melakukan perubahan pada kata tersebut, seandainya hanya tersisa 1 item.

Ketamakan

Sangat mudah untuk menggunakan replace untuk menulis fungsi yang menghapus semua komentar dari kode JavaScript. Inilah percobaan pertama:

Fungsi stripComments(kode) ( return code.replace(/\/\/.*|\/\*[^]*\*\//g, ""); ) console.log(stripComments("1 + /* 2 */3")); // → 1 + 3 console.log(stripComments("x = 10;// sepuluh!")); // → x = 10; console.log(stripComments("1 /* a */+/* b */ 1")); // → 1 1

Bagian sebelum operator "atau" cocok dengan dua garis miring yang diikuti oleh sejumlah karakter kecuali baris baru. Bagian yang menghapus komentar multi-baris lebih kompleks. Kami menggunakan [^], yaitu. karakter apa pun yang tidak kosong sebagai cara untuk menemukan karakter apa pun. Kami tidak dapat menggunakan titik karena pemblokiran komentar terus berlanjut baris baru, dan karakter baris baru tidak cocok dengan titik.

Namun keluaran dari contoh sebelumnya salah. Mengapa?

Bagian [^]* pertama-tama akan mencoba menangkap karakter sebanyak mungkin. Jika karena ini bagian selanjutnya dari urutan reguler tidak menemukan kecocokan, maka satu karakter akan dikembalikan dan dicoba lagi. Dalam contoh ini, algoritme mencoba mengambil seluruh baris, lalu memutarnya kembali. Setelah memutar kembali 4 karakter, dia akan menemukan */ di baris - dan ini bukan yang kami inginkan. Kami hanya ingin mengambil satu komentar, dan tidak sampai ke akhir baris dan menemukan komentar terakhir.

Oleh karena itu, kita katakan bahwa operator pengulangan (+, *, ?, dan ()) bersifat serakah, yang berarti mereka terlebih dahulu mengambil sebanyak yang mereka bisa dan kemudian kembali lagi. Jika Anda mengajukan pertanyaan setelah operator seperti ini (+?, *?, ??, ()?), mereka akan berubah menjadi tidak serakah, dan mulai menemukan kemunculan sekecil mungkin.

Dan itulah yang kami butuhkan. Dengan memaksa tanda bintang untuk menemukan kecocokan dalam jumlah karakter seminimal mungkin dalam satu baris, kita hanya menggunakan satu blok komentar, dan tidak lebih.

Fungsi stripComments(kode) ( return code.replace(/\/\/.*|\/\*[^]*?\*\//g, ""); ) console.log(stripComments("1 /* a */+/* b */ 1")); // → 1 + 1

Banyak kesalahan yang terjadi saat menggunakan operator yang serakah dibandingkan operator yang tidak serakah. Saat menggunakan operator berulang, selalu pertimbangkan operator yang tidak serakah terlebih dahulu.

Membuat objek RegExp secara dinamis

Dalam beberapa kasus, pola pastinya tidak diketahui pada saat kode ditulis. Misalnya, Anda perlu mencari nama pengguna di teks, dan mengapitnya di garis bawah. Karena Anda hanya akan mengetahui namanya setelah menjalankan program, Anda tidak dapat menggunakan notasi garis miring.

Namun Anda dapat membuat string dan menggunakan konstruktor RegExp. Berikut ini contohnya:

Var nama = "harry"; var text = "Dan Harry mempunyai bekas luka di dahinya."; var regexp = RegExp baru("\\b(" + nama + ")\\b", "gi"); console.log(text.replace(regexp, "_$1_")); // → Dan _Harry_ memiliki bekas luka di dahinya.

Saat membuat batas kata, kita harus menggunakan garis miring ganda karena kita menulisnya dalam baris biasa, dan bukan dalam urutan biasa dengan garis miring ke depan. Argumen kedua pada RegExp berisi opsi untuk ekspresi reguler - dalam kasus kami "gi", yaitu. global dan peka huruf besar-kecil.

Namun bagaimana jika namanya “dea+hlrd” (jika pengguna kita adalah seorang kulhatzker)? Hasilnya, kita akan mendapatkan ekspresi reguler yang tidak berarti yang tidak akan menemukan kecocokan dalam string.

Kita dapat menambahkan garis miring terbalik sebelum karakter apa pun yang tidak kita sukai. Kita tidak dapat menambahkan garis miring terbalik sebelum huruf karena \b atau \n adalah karakter khusus. Namun Anda dapat menambahkan garis miring sebelum karakter non-alfanumerik tanpa masalah.

Var nama = "dea+hlrd"; var text = "Dea+hlrd ini mengganggu semua orang."; var lolos = nama.replace(/[^\w\s]/g, "\\$&"); var regexp = RegExp baru("\\b(" + lolos + ")\\b", "gi"); console.log(text.replace(regexp, "_$1_")); // → _dea+hlrd_ ini membuat semua orang kesal.

metode pencarian

Metode indexOf tidak dapat digunakan dengan ekspresi reguler. Namun ada metode pencarian yang hanya mengharapkan ekspresi reguler. Seperti indexOf, ia mengembalikan indeks kemunculan pertama, atau -1 jika tidak ada yang terjadi.

Console.log(" kata".pencarian(/\S/)); // → 2 console.log(" ".search(/\S/)); // → -1

Sayangnya, tidak ada cara untuk memberitahu metode untuk mencari kecocokan yang dimulai pada offset tertentu (seperti yang dapat Anda lakukan dengan indexOf). Itu akan sangat membantu.

properti indeks terakhir

Metode exec juga tidak berfungsi cara yang nyaman mulai mencari dari posisi tertentu dalam string. Tapi itu memberikan cara yang tidak nyaman.

Objek regex memiliki properti. Salah satunya adalah source yang berisi string. Yang lainnya adalah lastIndex, yang mengontrol, dalam beberapa kondisi, di mana pencarian kejadian berikutnya akan dimulai.

Kondisi ini termasuk opsi global g harus ada, dan pencarian harus dilakukan menggunakan metode exec. Lagi keputusan yang masuk akal Akan mudah untuk mengizinkan argumen tambahan diteruskan ke exec, tetapi kecerdasan bukanlah fitur mendasar dari antarmuka regex JavaScript.

Pola var = /y/g; pola.lastIndex = 3; var pertandingan = pola.exec("xyzzy"); console.log(match.index); // → 4 console.log(pattern.lastIndex); // → 5

Jika pencarian berhasil, panggilan exec memperbarui properti lastIndex untuk menunjuk ke posisi setelah kejadian yang ditemukan. Jika tidak berhasil, lastIndex disetel ke nol - sama seperti lastIndex dari objek yang baru dibuat.

Saat menggunakan variabel reguler global dan beberapa panggilan exec, pembaruan lastIndex otomatis ini dapat menyebabkan masalah. Server reguler Anda dapat mulai mencari dari posisi kiri dari panggilan sebelumnya.

Var angka = /\d/g; console.log(digit.exec("ini dia: 1")); // → ["1"] console.log(digit.exec("dan ​​sekarang: 1")); // → batal

Lain efek yang menarik Opsi g mengubah cara kerja metode pencocokan. Saat dipanggil dengan opsi ini, alih-alih mengembalikan larik yang mirip dengan hasil exec, opsi ini akan menemukan semua kemunculan pola dalam string dan mengembalikan larik substring yang ditemukan.

Console.log("Pisang".cocok(/an/g)); // → ["sebuah", "sebuah"]

Jadi berhati-hatilah dengan variabel reguler global. Kasus-kasus di mana mereka diperlukan - ganti panggilan atau tempat di mana Anda secara khusus menggunakan lastIndex - mungkin merupakan semua kasus di mana mereka harus digunakan.

Siklus kejadian

Tugas umumnya adalah mengulangi semua kemunculan pola dalam string sehingga dapat mengakses objek kecocokan di badan perulangan menggunakan lastIndex dan exec.

Var input = "Garis dengan 3 angka di dalamnya... 42 dan 88."; var nomor = /\b(\d+)\b/g; pertandingan var; while (cocok = angka.exec(input)) console.log("Ditemukan", cocok, " pada ", cocok.index); // → Ditemukan 3 kali 14 // Ditemukan 42 kali 33 // Ditemukan 88 kali 40

Ini memanfaatkan fakta bahwa nilai penugasan adalah nilai yang diberikan. Dengan menggunakan match = re.exec(input) sebagai kondisi dalam perulangan while, kita mencari di awal setiap iterasi, menyimpan hasilnya dalam variabel, dan mengakhiri perulangan ketika semua kecocokan ditemukan.

Mengurai file INI

Untuk mengakhiri bab ini, mari kita lihat masalah menggunakan ekspresi reguler. Bayangkan kita sedang menulis sebuah program yang mengumpulkan informasi tentang musuh kita melalui Internet secara otomatis. (Kami tidak akan menulis keseluruhan program, hanya bagian yang membaca file pengaturan. Maaf.) Filenya terlihat seperti ini:

Mesin Pencari=http://www.google.com/search?q=$1 kedengkian=9.7 ; titik koma ditempatkan sebelum komentar; setiap bagian mengacu pada musuh yang berbeda fullname=Larry Doe type=tk bull website=http://www.geocities.com/CapeCanaveral/11451 fullname=Gargamel type=evil wizard outputdir=/home/marijn/enemies/gargamel

Format file sebenarnya (yang cukup banyak digunakan, dan biasa disebut INI) adalah sebagai berikut:

Baris kosong dan baris yang dimulai dengan titik koma diabaikan
- garis yang diapit tanda kurung siku memulai bagian baru
- baris yang berisi pengenal alfanumerik diikuti dengan = tambahkan pengaturan di bagian ini

Yang lainnya adalah data yang salah.

Tugas kita adalah mengubah string tersebut menjadi array objek, masing-masing dengan properti nama dan array pengaturan. Satu objek diperlukan untuk setiap bagian, dan objek lainnya diperlukan untuk pengaturan global di atas file.

Karena file perlu diurai baris demi baris, ada baiknya memulai dengan memecah file menjadi beberapa baris. Untuk melakukan ini, kami menggunakan string.split("\n") di Bab 6. Beberapa sistem operasi tidak menggunakan satu karakter \n untuk jeda baris, namun dua karakter - \r\n. Karena metode split menggunakan ekspresi reguler sebagai argumen, kita dapat memisahkan baris menggunakan ekspresi /\r?\n/, yang memungkinkan \n dan \r\n antar baris.

Fungsi parseINI(string) ( // Mari kita mulai dengan objek yang berisi pengaturan tingkat atas var currentSection = (nama: null, bidang: );

var kategori = ;

string.split(/\r?\n/).forEach(function(line) ( var match; if (/^\s*(;.*)?$/.test(line)) ( return; ) else if (cocok = baris.cocok(/^\[(.*)\]$/)) ( currentSection = (nama: cocok, bidang: ); kategori.push(currentSection); ) else if (cocok = baris.cocok( /^(\w+)=(.*)$/)) ( currentSection.fields.push((nama: cocok, nilai: cocok)); ) else ( throw new Error("Baris "" + baris + "" berisi data salah."); ) ));

kategori pengembalian; )

Kode melewati semua baris, memperbarui objek bagian saat ini "bagian saat ini". Pertama, ia memeriksa apakah baris dapat diabaikan menggunakan ekspresi reguler /^\s*(;.*)?$/. Bisakah Anda bayangkan cara kerjanya? Bagian di antara tanda kurung cocok dengan komentar ya? membuatnya agar karakter biasa juga akan cocok dengan garis yang hanya terdiri dari spasi.

Jika baris tersebut bukan komentar, kode akan memeriksa apakah baris tersebut memulai bagian baru. Jika ya, ini akan membuat objek baru untuk bagian saat ini, yang mana pengaturan berikutnya akan ditambahkan.

Kemungkinan terakhir yang berarti adalah bahwa string tersebut merupakan pengaturan normal, dalam hal ini string tersebut ditambahkan ke objek saat ini.

Jika tidak ada opsi yang berfungsi, fungsi akan menimbulkan kesalahan.

Perhatikan bagaimana seringnya penggunaan ^ dan $ memastikan bahwa ekspresi tersebut cocok dengan keseluruhan string, bukan hanya sebagian saja. Jika Anda tidak menggunakannya, kode tersebut secara umum akan berfungsi, tetapi terkadang memberikan hasil yang aneh dan kesalahannya akan sulit dilacak.

Anehnya, secara historis \s (spasi) cocok dengan semua karakter yang dianggap spasi putih di Unicode, termasuk karakter seperti spasi tak putus atau pemisah vokal Mongolia.

Beberapa implementasi regex dalam bahasa lain memiliki sintaks khusus untuk mencari kategori karakter Unicode khusus, seperti "all huruf kapital", "semua tanda baca" atau "karakter kontrol". Ada rencana untuk menambahkan kategori seperti itu ke JavaScript, namun kemungkinan besar tidak akan diterapkan dalam waktu dekat.

Intinya

Regular adalah objek yang mewakili pola pencarian dalam string. Mereka menggunakan sintaksis mereka sendiri untuk mengekspresikan pola-pola ini.

/abc/ Urutan karakter
// Karakter apa pun dari daftar
/[^abc]/ Karakter apa pun kecuali karakter dari daftar
// Karakter apa pun dari interval
/x+/ Satu atau lebih kemunculan pola x
/x+?/ Satu atau lebih kemunculan, tidak serakah
/x*/ Nol atau lebih kemunculan
/x?/ Nol atau satu kejadian
/x(2,4)/ Dari dua hingga empat kemunculan
/(abc)/ Grup
/a|b|c/ Salah satu dari beberapa pola
/\d/ Nomor berapa pun
/\w/ Karakter alfanumerik apa pun (“huruf”)
/\s/ Karakter spasi apa pun
/./ Karakter apa pun kecuali jeda baris
/\b/ Batas kata
/^/ Awal baris
/$/ Akhir baris

Regex memiliki metode pengujian untuk memeriksa apakah polanya ada dalam string. Ada metode exec yang mengembalikan array yang berisi semua grup yang ditemukan. Array memiliki properti indeks, yang berisi jumlah karakter asal kecocokan.

String memiliki metode pencocokan untuk mencocokkan pola, dan metode pencarian yang hanya mengembalikan posisi awal kemunculannya. Metode ganti dapat mengganti kemunculan suatu pola dengan string lain. Selain itu, Anda dapat meneruskan fungsi pengganti yang akan membuat baris pengganti berdasarkan templat dan grup yang ditemukan.

Karakter biasa memiliki pengaturan yang ditulis setelah garis miring penutup. Opsi i menjadikan ekspresi reguler tidak peka huruf besar-kecil, dan opsi g menjadikannya global, yang, antara lain, menyebabkan metode replace menggantikan semua kemunculan yang ditemukan, bukan hanya yang pertama.

Konstruktor RegExp dapat digunakan untuk membuat ekspresi reguler dari string.

Regulator adalah instrumen tajam dengan pegangan yang tidak nyaman. Mereka sangat menyederhanakan beberapa tugas, dan bisa menjadi tidak terkendali ketika memecahkan masalah lain yang kompleks. Bagian dari belajar menggunakan regex adalah untuk mampu menahan godaan untuk mengisinya dengan tugas yang tidak dimaksudkan.

Latihan

Tak pelak lagi, saat memecahkan masalah, Anda akan menghadapi kasus-kasus yang tidak dapat dipahami, dan terkadang Anda mungkin putus asa ketika melihat perilaku beberapa ekspresi reguler yang tidak dapat diprediksi. Terkadang mempelajari perilaku mesin biasa melalui layanan online seperti debuggex.com membantu, di mana Anda dapat melihat visualisasinya dan membandingkannya dengan efek yang diinginkan.
Golf biasa
“Golf” dalam kode adalah permainan di mana Anda perlu berekspresi program yang diberikan jumlah minimum karakter. Golf reguler adalah latihan praktis dalam menulis regular terkecil untuk menemukan pola tertentu, dan hanya itu.

Untuk setiap subbaris, tulis ekspresi reguler untuk memeriksa lokasinya di baris. Mesin reguler seharusnya hanya menemukan substring tertentu ini. Jangan khawatir tentang batasan kata kecuali disebutkan secara khusus. Jika Anda memiliki pola kerja teratur, cobalah menguranginya.

Mobil dan kucing
- pop dan penyangga
- musang, feri, dan ferrari
- Kata apa pun yang berakhiran ious
- Spasi diikuti titik, koma, titik dua, atau titik koma.
- Sebuah kata yang panjangnya lebih dari enam huruf
- Kata tanpa huruf e

// Masukkan ekspresi reguler verifikasi(/.../, ["mobil saya", "kucing nakal"], ["camper", "seni tinggi"]); verifikasi(/.../, ["budaya pop", "alat peraga gila"], ["plop"]); verifikasi(/.../, ["musang", "feri", "ferrari"], ["ferrum", "transfer A"]); verifikasi(/.../, ["betapa enak", "ruangan luas"], ["merusak", "kesadaran"]); verifikasi(/.../, ["tanda baca buruk ."], ["escape the dot"]); verifikasi(/.../, ["hottenottententen"], ["tidak", "hotten totten tenten"]); verifikasi(/.../, ["platipus merah", "sarang goyangan"], ["alas tanah", "kera belajar"]); function verifikasi(regexp, yes, no) ( // Abaikan latihan yang belum selesai if (regexp.source == "...") return; yes.forEach(function(s) ( if (!regexp.test(s)) console .log("Tidak ditemukan "" + s + """ )); no.forEach(function(s) ( if (regexp.test(s)) console.log("Kejadian tak terduga "" + s + " "" );

Kutipan dalam teks
Katakanlah Anda menulis sebuah cerita, dan di mana pun Anda biasa menunjukkan dialog kutipan tunggal. Sekarang Anda ingin mengganti tanda kutip dialog dengan tanda kutip ganda, dan membiarkan tanda kutip tunggal dalam singkatan untuk kata-kata seperti bukan.

Buatlah pola yang membedakan kedua penggunaan tanda kutip ini, dan tuliskan panggilan ke metode penggantian yang melakukan penggantian.

Angka lagi
Urutan angka dapat ditemukan dengan ekspresi reguler sederhana /\d+/.

Tulis ekspresi yang hanya menemukan angka yang ditulis dalam gaya JavaScript. Itu harus mendukung kemungkinan minus atau plus sebelum angka, titik desimal, dan notasi ilmiah 5e-3 atau 1E10 - sekali lagi dengan kemungkinan plus atau minus. Perhatikan juga bahwa belum tentu ada angka sebelum atau sesudah titik, tetapi angka tersebut tidak boleh terdiri dari satu titik. Artinya, 0,5 atau 5 adalah bilangan valid, namun satu titik saja bukan bilangan valid.

// Masukkan urutan reguler di sini. var nomor = /^...$/; // Pengujian: ["1", "-1", "+15", "1.55", ".5", "5.", "1.3e2", "1E-4", "1e+12"] .forEach(function(s) ( if (!number.test(s)) console.log("Tidak menemukan "" + s + """); )); ["1a", "+-1", "1.2.3", "1+1", "1e4.5", ".5.", "1f5", "."].forEach(fungsi) ( if (number.test(s)) console.log("Salah diterima "" + s + """); ));

Beberapa orang, ketika dihadapkan pada suatu masalah, berpikir: “Oh, saya akan menggunakan ekspresi reguler.” Sekarang mereka punya dua masalah.
Jamie Zawinski

Yuan-Ma berkata, “Dibutuhkan banyak tenaga untuk memotong kayu melintasi serat kayu. Dibutuhkan banyak kode untuk memprogram seluruh struktur masalah.
Master Yuan-Ma, “Buku Pemrograman”

Alat dan teknik pemrograman bertahan dan menyebar secara evolusioner dan kacau. Kadang-kadang bukan orang-orang cantik dan cemerlang yang bisa bertahan, tapi mereka yang bekerja cukup baik di bidangnya - misalnya, jika mereka diintegrasikan ke dalam teknologi sukses lainnya.

Dalam bab ini, kita akan membahas alat seperti itu - ekspresi reguler. Ini adalah cara untuk mendeskripsikan pola dalam data string. Mereka membuat bahasa kecil yang berdiri sendiri yang disertakan dalam JavaScript dan banyak bahasa serta alat lainnya.

Jadwal rutinnya sangat aneh dan sangat berguna. Sintaksnya samar dan antarmuka pemrograman JavaScript-nya kikuk. Tapi ini adalah alat yang ampuh untuk mengeksplorasi dan memanipulasi string. Setelah Anda memahaminya, Anda akan menjadi programmer yang lebih efektif.

Membuat ekspresi reguler

Reguler – tipe objek. Itu dapat dibuat dengan memanggil konstruktor RegExp, atau dengan menulis template yang diinginkan, diapit oleh garis miring.

Var re1 = RegExp baru("abc"); var re2 = /abc/;

Kedua ekspresi reguler ini mewakili pola yang sama: karakter “a” diikuti oleh karakter “b” diikuti oleh karakter “c”.

Jika Anda menggunakan konstruktor RegExp, maka polanya ditulis sebagai string biasa, sehingga semua aturan mengenai garis miring terbalik berlaku.

Entri kedua, yang polanya berada di antara garis miring, menangani garis miring terbalik secara berbeda. Pertama, karena polanya diakhiri dengan garis miring, kita perlu meletakkan garis miring terbalik sebelum garis miring yang ingin kita sertakan dalam pola kita. Selain itu, garis miring terbalik yang bukan bagian dari karakter khusus seperti \n akan dipertahankan (daripada diabaikan seperti pada string), dan akan mengubah arti polanya. Beberapa karakter, seperti tanda tanya atau plus, memiliki arti khusus dalam ekspresi reguler, dan jika perlu mencari karakter seperti itu, karakter tersebut juga harus diawali dengan garis miring terbalik.

Var delapan belasPlus = /delapan belas\+/;

Untuk mengetahui karakter mana yang perlu diawali dengan garis miring, Anda perlu mempelajari daftar semua karakter khusus dalam ekspresi reguler. Hal ini belum bisa dilakukan, jadi jika ragu, cukup beri tanda garis miring terbalik di depan karakter apa pun yang bukan huruf, angka, atau spasi.

Memeriksa kecocokan

Regular memiliki beberapa metode. Yang paling sederhana adalah tes. Jika Anda meneruskannya sebuah string, ia akan mengembalikan nilai Boolean yang menunjukkan apakah string tersebut berisi kemunculan pola yang diberikan.

Console.log(/abc/.test("abcde")); // → true console.log(/abc/.test("abxde")); // → salah

Urutan reguler yang hanya terdiri dari karakter non-khusus hanyalah urutan karakter tersebut. Jika abc berada di mana saja pada baris yang kita uji (tidak hanya di awal), pengujian akan menghasilkan nilai true.

Mencari sekumpulan karakter

Anda juga bisa mengetahui apakah suatu string berisi abc menggunakan indexOf. Pola teratur memungkinkan Anda melangkah lebih jauh dan membuat pola yang lebih kompleks.

Katakanlah kita perlu mencari nomor apa pun. Saat kita meletakkan sekumpulan karakter dalam tanda kurung siku pada ekspresi reguler, artinya bagian ekspresi tersebut cocok dengan salah satu karakter dalam tanda kurung.

Kedua ekspresi tersebut berada dalam baris yang berisi angka.

Console.log(//.test("pada tahun 1992")); // → true console.log(//.test("pada tahun 1992")); // → benar

Dalam tanda kurung siku, tanda hubung antara dua karakter digunakan untuk menentukan rentang karakter, yang urutannya ditentukan oleh pengkodean Unicode. Karakter dari 0 hingga 9 hanya ada dalam satu baris (kode dari 48 hingga 57), sehingga karakter tersebut menangkap semuanya dan mencocokkan nomor apa pun.

Beberapa kelompok karakter mempunyai singkatan tersendiri.

\d Nomor berapa saja
\w Karakter alfanumerik
\s Karakter spasi putih (spasi, tab, baris baru, dll.)
\D bukan angka
\W bukan karakter alfanumerik
\S bukan karakter spasi
. karakter apa pun kecuali umpan baris

Dengan demikian, Anda dapat mengatur format tanggal dan waktu seperti 30/01/2003 15:20 dengan ekspresi berikut:

Var tanggalWaktu = /\d\d-\d\d-\d\d\d\d \d\d:\d\d/; console.log(dateTime.test("30-01-2003 15:20")); // → true console.log(dateTime.test("30-Jan-2003 15:20")); // → salah

Terlihat mengerikan, bukan? Terlalu banyak garis miring terbalik, sehingga polanya sulit dipahami. Kami akan memperbaikinya sedikit nanti.

Garis miring terbalik juga dapat digunakan dalam tanda kurung siku. Misalnya, [\d.] berarti angka atau titik apa pun. Perhatikan bahwa periode di dalam tanda kurung siku kehilangan arti khususnya dan hanya menjadi sebuah periode. Hal yang sama berlaku untuk karakter khusus lainnya, seperti +.

Anda dapat membalikkan sekumpulan karakter - yaitu, katakanlah Anda perlu mencari karakter apa pun kecuali karakter yang ada dalam kumpulan tersebut - dengan menempatkan tanda ^ tepat setelah tanda kurung siku pembuka.

Var notBinary = /[^01]/; console.log(notBinary.test("1100100010100110")); // → false console.log(notBinary.test("1100100010200110")); // → benar

Mengulangi bagian template

Kami tahu cara menemukan satu nomor. Bagaimana jika kita perlu mencari bilangan bulat - barisan satu atau lebih digit?

Jika Anda memberi tanda + setelah sesuatu dalam urutan yang benar, ini berarti elemen tersebut dapat diulang lebih dari satu kali. /\d+/ berarti satu atau lebih digit.

Console.log(/"\d+"/.test(""123"")); // → true console.log(/"\d+"/.test("""")); // → false console.log(/"\d*"/.test(""123"")); // → true console.log(/"\d*"/.test("""")); // → benar

Tanda bintang * mempunyai arti yang hampir sama, namun memungkinkan pola muncul sebanyak nol kali. Jika sesuatu diikuti oleh tanda bintang, maka hal itu tidak pernah menghalangi pola untuk berada dalam garis - hanya muncul di sana nol kali.

Tanda tanya membuat bagian dari pola menjadi opsional, artinya dapat muncul nol atau satu kali. Dalam contoh berikut, karakter u mungkin muncul, namun polanya cocok meskipun tidak.

Var tetangga = /tetangga?r/; console.log(neighbor.test("neighbor")); // → true console.log(neighbor.test("neighbor")); // → benar

Kurung kurawal digunakan untuk menentukan berapa kali suatu pola harus muncul. (4) setelah suatu elemen berarti harus muncul 4 kali dalam satu baris. Anda juga dapat menentukan celah: (2,4) berarti elemen tersebut harus muncul minimal 2 dan tidak lebih dari 4 kali.

Versi lain dari format tanggal dan waktu, di mana hari, bulan, dan jam diperbolehkan satu atau dua digit. Dan itu juga sedikit lebih mudah dibaca.

Var tanggalWaktu = /\d(1,2)-\d(1,2)-\d(4) \d(1,2):\d(2)/; console.log(dateTime.test("30-1-2003 8:45")); // → benar

Anda dapat menggunakan ruang terbuka dengan menghilangkan salah satu nomornya. (,5,) berarti pola tersebut dapat muncul dari nol hingga lima kali, dan (5,) berarti lima kali atau lebih.

Mengelompokkan Subekspresi

Untuk menggunakan operator * atau + pada beberapa elemen sekaligus, Anda dapat menggunakan tanda kurung. Bagian dari ekspresi reguler yang diapit tanda kurung dianggap sebagai salah satu elemen dari sudut pandang operator.

Var kartunMenangis = /boo+(hoo+)+/i; console.log(cartoonCrying.test("Boohoooohoohooo")); // → benar

Tanda plus pertama dan kedua hanya berlaku untuk huruf o kedua dalam boo dan hoo. + ketiga mengacu pada keseluruhan grup (hoo+), menemukan satu atau lebih urutan tersebut.

Huruf i di akhir ekspresi membuat ekspresi reguler tidak peka huruf besar-kecil - sehingga B cocok dengan b.

Pertandingan dan Grup

Metode pengujian adalah metode paling sederhana untuk memeriksa ekspresi reguler. Ini hanya memberi tahu Anda apakah kecocokan ditemukan atau tidak. Regular juga memiliki metode exec, yang akan mengembalikan null jika tidak ada yang ditemukan, dan sebaliknya mengembalikan objek dengan informasi tentang kecocokan.

Var pertandingan = /\d+/.exec("satu dua 100"); console.log(cocok); // → ["100"] console.log(match.index); // → 8

Objek yang dikembalikan oleh exec memiliki properti indeks, yang berisi jumlah karakter asal kecocokan. Secara umum, objek terlihat seperti array string, dimana elemen pertama adalah string yang diperiksa kecocokannya. Dalam contoh kita, ini adalah urutan angka yang kita cari.

String memiliki metode pencocokan yang bekerja dengan cara yang hampir sama.

Console.log("satu dua 100".cocok(/\d+/)); // → ["100"]

Jika ekspresi reguler berisi subekspresi yang dikelompokkan berdasarkan tanda kurung, teks yang cocok dengan grup ini juga akan muncul dalam array. Elemen pertama selalu merupakan kecocokan yang lengkap. Bagian kedua adalah bagian yang cocok dengan kelompok pertama (yang tanda kurungnya muncul lebih dulu), kemudian kelompok kedua, dan seterusnya.

Var quoteText = /"([^"]*)"/; console.log(quotedText.exec("dia berkata "halo"")); // → [""halo"", "halo"]

Jika suatu grup tidak ditemukan sama sekali (misalnya, jika diikuti dengan tanda tanya), posisinya dalam larik tidak ditentukan. Jika sebuah grup cocok beberapa kali, maka hanya pertandingan terakhir yang akan ada dalam array.

Console.log(/bad(ly)?/.exec("bad")); // → ["buruk", tidak terdefinisi] console.log(/(\d)+/.exec("123")); // → ["123", "3"]

Grup berguna untuk mengambil bagian dari string. Jika kita tidak hanya ingin memeriksa apakah suatu string memiliki tanggal, tetapi mengekstraknya dan membuat objek yang mewakili tanggal tersebut, kita dapat menyertakan urutan angka dalam tanda kurung dan memilih tanggal dari hasil exec.

Tapi pertama-tama, sedikit penyimpangan di mana kita akan mempelajari cara yang lebih disukai untuk menyimpan tanggal dan waktu dalam JavaScript.

Jenis tanggal

JavaScript memiliki tipe objek standar untuk tanggal—lebih khusus lagi, momen dalam waktu. Namanya Tanggal. Jika Anda hanya membuat objek tanggal menggunakan yang baru, Anda akan mendapatkan tanggal dan waktu saat ini.

Console.log(Tanggal baru()); // → Minggu 09 Nov 2014 00:07:57 GMT+0300 (CET)

Anda juga dapat membuat objek yang berisi waktu tertentu

Console.log(Tanggal baru(2015, 9, 21)); // → Rabu 21 Okt 2015 00:00:00 GMT+0300 (CET) console.log(Tanggal baru(2009, 11, 9, 12, 59, 59, 999)); // → Rabu 09 Des 2009 12:59:59 GMT+0300 (CET)

JavaScript menggunakan konvensi di mana angka bulan dimulai dengan angka nol dan angka hari dimulai dengan angka satu. Ini bodoh dan konyol. Hati-Hati.

Empat argumen terakhir (jam, menit, detik, dan milidetik) bersifat opsional dan disetel ke nol jika tidak ada.

Stempel waktu disimpan sebagai jumlah milidetik yang telah berlalu sejak awal tahun 1970. Untuk masa sebelum tahun 1970, angka negatif digunakan (hal ini disebabkan oleh konvensi waktu Unix yang dibuat sekitar waktu itu). Metode getTime objek tanggal mengembalikan nomor ini. Tentu saja ukurannya besar.
console.log(Tanggal baru(2013, 11, 19).getTime()); // → 1387407600000 console.log(Tanggal baru(1387407600000)); // → Kam 19 Des 2013 00:00:00 GMT+0100 (CET)

Jika Anda memberikan satu argumen kepada konstruktor Tanggal, argumen tersebut akan diperlakukan sebagai jumlah milidetik ini. Anda bisa mendapatkan nilai milidetik saat ini dengan membuat objek Date dan memanggil metode getTime, atau dengan memanggil fungsi Date.now.

Objek Tanggal memiliki metode getFullYear, getMonth, getDate, getHours, getMinutes, dan getSeconds untuk mengambil komponennya. Ada juga metode getYear yang mengembalikan kode dua digit yang tidak berguna seperti 93 atau 14.

Dengan menyertakan bagian template yang relevan dalam tanda kurung, kita dapat membuat objek tanggal langsung dari string.

Fungsi findDate(string) ( var dateTime = /(\d(1,2))-(\d(1,2))-(\d(4))/; var match = dateTime.exec(string); return Tanggal baru(Nomor(pertandingan), Nomor(pertandingan) - 1, Nomor(pertandingan) ) console.log(findDate("30-1-2003")); // → Kam 30 Jan 2003 00:00:00 GMT+0100 (CET)

Batas kata dan garis

Sayangnya, findDate dengan senang hati akan mengekstrak tanggal tidak berarti 00-1-3000 dari string "100-1-30000". Pencocokan dapat terjadi di mana saja dalam string, jadi dalam hal ini pencocokan hanya akan dimulai pada karakter kedua dan berakhir pada karakter kedua hingga terakhir.

Jika kita perlu memaksa kecocokan untuk mengambil seluruh string, kita menggunakan tag ^ dan $. ^ cocok dengan awal baris, dan $ cocok dengan akhir. Oleh karena itu, /^\d+$/ cocok dengan string yang hanya berisi satu digit atau lebih, /^!/ cocok dengan string yang dimulai dengan tanda seru, dan /x^/ tidak cocok dengan string mana pun (tidak boleh ada x).

Sebaliknya, jika kita hanya ingin memastikan bahwa tanggal dimulai dan diakhiri pada batas kata, kita menggunakan tanda \b. Batas kata dapat berupa awal atau akhir baris, atau tempat mana pun dalam baris yang terdapat karakter alfanumerik \w di satu sisi dan karakter non-alfanumerik di sisi lain.

Console.log(/cat/.test("menggabungkan")); // → true console.log(/\bcat\b/.test("concatenate")); // → salah

Perhatikan bahwa label batas bukanlah sebuah simbol. Ini hanyalah sebuah batasan yang berarti kecocokan hanya terjadi jika kondisi tertentu terpenuhi.

Templat dengan pilihan

Katakanlah Anda perlu mencari tahu apakah teks tersebut tidak hanya berisi angka, tetapi angka yang diikuti oleh babi, sapi, atau ayam dalam bentuk tunggal atau jamak.

Dimungkinkan untuk menulis tiga ekspresi reguler dan memeriksanya satu per satu, tetapi ada cara yang lebih baik. Simbol | menunjukkan pilihan antara pola di kiri dan kanannya. Dan kami dapat mengatakan yang berikut:

Var animalCount = /\b\d+ (babi|sapi|ayam)s?\b/; console.log(animalCount.test("15 babi")); // → true console.log(animalCount.test("15 ekor babi")); // → salah

Tanda kurung membatasi bagian pola yang | diterapkan, dan banyak operator seperti itu dapat ditempatkan satu demi satu untuk menunjukkan pilihan dari lebih dari dua opsi.

Mesin Pencari

Ekspresi reguler dapat dianggap sebagai diagram alur. Diagram berikut menjelaskan contoh peternakan terkini.

Suatu ekspresi cocok dengan string jika dimungkinkan untuk menemukan jalur dari sisi kiri diagram ke kanan. Kita ingat posisi saat ini dalam garis, dan setiap kali kita melewati persegi panjang, kita memeriksa apakah bagian garis tepat setelah posisi kita di dalamnya cocok dengan isi persegi panjang.

Ini berarti memeriksa apakah karakter reguler kita cocok dengan string “3 babi” saat menelusuri diagram alur akan terlihat seperti ini:

Di posisi 4 ada batas kata, dan kita melewati persegi panjang pertama
- mulai dari posisi ke-4 kita cari nomornya dan lewati persegi panjang kedua
- pada posisi 5, satu jalur menutup kembali di depan persegi panjang kedua, dan jalur kedua berlanjut lebih jauh ke persegi panjang yang diberi spasi. Kami memiliki spasi, bukan angka, dan kami memilih jalur kedua.
- sekarang kita berada di posisi 6, awal dari “babi”, dan di tiga percabangan jalan. Tidak ada “sapi” atau “ayam” di antrean, tapi ada “babi”, jadi kami memilih jalan ini.
- pada posisi 9 setelah pertigaan tiga kali lipat, satu jalur melewati "s" dan menuju ke persegi panjang batas kata terakhir, dan jalur kedua melewati "s". Kami memiliki huruf "s" jadi kami pergi ke sana.
- pada posisi 10 kita berada di ujung baris, dan hanya batas kata saja yang bisa cocok. Ujung garis dianggap sebagai batas, dan kita melewati persegi panjang terakhir. Dan sekarang kita telah berhasil menemukan template kita.

Pada dasarnya, cara kerja ekspresi reguler adalah algoritme dimulai dari awal string dan mencoba menemukan kecocokan di sana. Dalam kasus kita, ada batas kata, sehingga melewati persegi panjang pertama - tetapi tidak ada angka di sana, sehingga tersandung pada persegi panjang kedua. Kemudian berpindah ke karakter kedua dalam string, dan mencoba menemukan kecocokan di sana... Dan seterusnya hingga menemukan kecocokan atau mencapai akhir string, dalam hal ini tidak ditemukan kecocokan.

suap

Ekspresi reguler /\b(+b|\d+|[\da-f]h)\b/ cocok dengan bilangan biner yang diikuti oleh a b, bilangan desimal tanpa akhiran, atau bilangan heksadesimal (angka 0 hingga 9 atau simbol dari a sampai h), diikuti h. Diagram yang relevan:

Saat mencari kecocokan, mungkin saja algoritme mengambil jalur teratas (bilangan biner), meskipun tidak ada nomor tersebut dalam string. Jika ada garis “103”, misalnya, jelas baru setelah mencapai angka 3 algoritma akan memahami bahwa ia berada di jalur yang salah. Secara umum, garis tersebut cocok dengan urutan reguler, hanya saja tidak di thread ini.

Kemudian algoritme diputar kembali. Di pertigaan, ia mengingat posisi saat ini (dalam kasus kami, ini adalah awal baris, tepat setelah batas kata) sehingga Anda dapat kembali dan mencoba jalur lain jika jalur yang dipilih tidak berhasil. Untuk string “103”, setelah menemukan angka tiga, ia akan kembali dan mencoba melewati jalur desimal. Ini akan berhasil sehingga kecocokan akan ditemukan.

Algoritme berhenti segera setelah menemukan kecocokan yang lengkap. Artinya, meskipun beberapa opsi mungkin cocok, hanya satu opsi yang digunakan (sesuai urutan kemunculannya dalam urutan biasa).

Backtracking terjadi ketika menggunakan operator pengulangan seperti + dan *. Jika Anda mencari /^.*x/ di string "abcxe", bagian regex.* akan mencoba menggunakan seluruh string. Algoritme kemudian akan menyadari bahwa ia juga membutuhkan “x”. Karena tidak ada “x” setelah akhir string, algoritme akan mencoba mencari kecocokan dengan memundurkan satu karakter. Setelah abcx juga tidak ada x, lalu roll kembali lagi, kali ini ke substring abc. Dan setelah garis tersebut, ia menemukan x dan melaporkan kecocokan yang berhasil, di posisi 0 hingga 4.

Anda dapat menulis rutinitas rutin yang akan menyebabkan banyak kemunduran. Masalah ini terjadi ketika pola dapat mencocokkan masukan dalam berbagai cara. Misalnya, jika kita membuat kesalahan saat menulis ekspresi reguler untuk bilangan biner, kita mungkin secara tidak sengaja menulis sesuatu seperti /(+)+b/.

Jika algoritme mencari pola seperti itu dalam string panjang 0 dan 1 yang tidak memiliki "b" di akhir, algoritme tersebut akan melewati loop dalam terlebih dahulu hingga kehabisan digit. Kemudian dia akan menyadari bahwa tidak ada "b" di akhir, dia akan memutar kembali satu posisi, melewati loop luar, menyerah lagi, mencoba memutar kembali ke posisi lain di sepanjang loop dalam... Dan dia akan melanjutkan untuk mencari dengan cara ini, menggunakan kedua loop. Artinya, jumlah pekerjaan dengan setiap karakter baris akan berlipat ganda. Bahkan untuk beberapa lusin karakter, menemukan kecocokan akan memakan waktu yang sangat lama.

ganti metode

String memiliki metode replace yang dapat mengganti sebagian string dengan string lain.

Console.log("ayah".replace("p", "m")); // → peta

Argumen pertama juga bisa berupa ekspresi reguler, dalam hal ini kemunculan pertama ekspresi reguler dalam baris akan diganti. Ketika opsi “g” (global) ditambahkan ke regex, semua kemunculan diganti, bukan hanya yang pertama

Console.log("Borobudur".replace(//, "a")); // → Barobudur console.log("Borobudur".replace(//g, "a")); // → Barabadar

Masuk akal untuk meneruskan opsi "ganti semua" melalui argumen terpisah, atau melalui metode terpisah seperti replaceAll. Namun sayangnya, opsi tersebut ditularkan melalui sistem reguler itu sendiri.

Kekuatan penuh dari ekspresi reguler terungkap ketika kita menggunakan tautan ke grup yang ditemukan dalam sebuah string, yang ditentukan dalam ekspresi reguler. Misalnya, kita mempunyai baris yang berisi nama orang, satu nama per baris, dalam format "Nama Belakang, Nama Depan". Jika kita perlu menukarnya dan menghapus koma untuk mendapatkan “Nama Depan Nama Belakang”, kita menulis yang berikut:

Console.log("Hopper, Grace\nMcCarthy, John\nRitchie, Dennis" .replace(/([\w ]+), ([\w ]+)/g, "$2 $1")); // → Grace Hopper // John McCarthy // Dennis Ritchie

$1 dan $2 pada baris pengganti mengacu pada kelompok karakter yang diapit tanda kurung. $1 diganti dengan teks yang cocok dengan grup pertama, $2 dengan grup kedua, dan seterusnya hingga $9. Keseluruhan kecocokan terkandung dalam variabel $&.

Anda juga bisa meneruskan fungsi sebagai argumen kedua. Untuk setiap penggantian, suatu fungsi akan dipanggil yang argumennya adalah grup yang ditemukan (dan seluruh bagian baris yang cocok), dan hasilnya akan dimasukkan ke dalam baris baru.

Contoh sederhana:

Var s = "cia dan fbi"; console.log(s.replace(/\b(fbi|cia)\b/g, function(str) ( return str.toUpperCase(); ))); // → CIA dan FBI

Ini yang lebih menarik:

Var stock = "1 buah lemon, 2 buah kubis, dan 101 butir telur"; function minusOne(match, amount, unit) ( amount = Number(amount) - 1; if (amount == 1) // hanya tersisa satu, hilangkan tanda "s" di akhir unit = unit.slice(0, unit. panjang - 1); else if (jumlah == 0) jumlah = "tidak"; jumlah yang dikembalikan + " " + unit; ) console.log(stock.replace(/(\d+) (\w+)/g, minusOne) ); // → tanpa lemon, 1 kubis, dan 100 butir telur

Kode mengambil sebuah string, menemukan semua kemunculan angka yang diikuti oleh sebuah kata, dan mengembalikan sebuah string dengan setiap angka dikurangi satu.

Grup (\d+) masuk ke argumen jumlah, dan (\w+) masuk ke argumen unit. Fungsi ini mengubah jumlah menjadi angka - dan ini selalu berhasil, karena pola kita adalah \d+. Dan kemudian melakukan perubahan pada kata tersebut, seandainya hanya tersisa 1 item.

Ketamakan

Sangat mudah untuk menggunakan replace untuk menulis fungsi yang menghapus semua komentar dari kode JavaScript. Inilah percobaan pertama:

Fungsi stripComments(kode) ( return code.replace(/\/\/.*|\/\*[^]*\*\//g, ""); ) console.log(stripComments("1 + /* 2 */3")); // → 1 + 3 console.log(stripComments("x = 10;// sepuluh!")); // → x = 10; console.log(stripComments("1 /* a */+/* b */ 1")); // → 1 1

Bagian sebelum operator "atau" cocok dengan dua garis miring yang diikuti oleh sejumlah karakter kecuali baris baru. Bagian yang menghapus komentar multi-baris lebih kompleks. Kami menggunakan [^], yaitu. karakter apa pun yang tidak kosong sebagai cara untuk menemukan karakter apa pun. Kita tidak dapat menggunakan titik karena blok komentar berlanjut pada baris baru, dan karakter baris baru tidak sesuai dengan titik.

Namun keluaran dari contoh sebelumnya salah. Mengapa?

Bagian [^]* pertama-tama akan mencoba menangkap karakter sebanyak mungkin. Jika karena ini bagian selanjutnya dari urutan reguler tidak menemukan kecocokan, maka satu karakter akan dikembalikan dan dicoba lagi. Dalam contoh ini, algoritme mencoba mengambil seluruh baris, lalu memutarnya kembali. Setelah memutar kembali 4 karakter, dia akan menemukan */ di baris - dan ini bukan yang kami inginkan. Kami hanya ingin mengambil satu komentar, dan tidak sampai ke akhir baris dan menemukan komentar terakhir.

Oleh karena itu, kita katakan bahwa operator pengulangan (+, *, ?, dan ()) bersifat serakah, yang berarti mereka terlebih dahulu mengambil sebanyak yang mereka bisa dan kemudian kembali lagi. Jika Anda mengajukan pertanyaan setelah operator seperti ini (+?, *?, ??, ()?), mereka akan berubah menjadi tidak serakah, dan mulai menemukan kemunculan sekecil mungkin.

Dan itulah yang kami butuhkan. Dengan memaksa tanda bintang untuk menemukan kecocokan dalam jumlah karakter seminimal mungkin dalam satu baris, kita hanya menggunakan satu blok komentar, dan tidak lebih.

Fungsi stripComments(kode) ( return code.replace(/\/\/.*|\/\*[^]*?\*\//g, ""); ) console.log(stripComments("1 /* a */+/* b */ 1")); // → 1 + 1

Banyak kesalahan yang terjadi saat menggunakan operator yang serakah dibandingkan operator yang tidak serakah. Saat menggunakan operator berulang, selalu pertimbangkan operator yang tidak serakah terlebih dahulu.

Membuat objek RegExp secara dinamis

Dalam beberapa kasus, pola pastinya tidak diketahui pada saat kode ditulis. Misalnya, Anda perlu mencari nama pengguna di teks, dan mengapitnya di garis bawah. Karena Anda hanya akan mengetahui namanya setelah menjalankan program, Anda tidak dapat menggunakan notasi garis miring.

Namun Anda dapat membuat string dan menggunakan konstruktor RegExp. Berikut ini contohnya:

Var nama = "harry"; var text = "Dan Harry mempunyai bekas luka di dahinya."; var regexp = RegExp baru("\\b(" + nama + ")\\b", "gi"); console.log(text.replace(regexp, "_$1_")); // → Dan _Harry_ memiliki bekas luka di dahinya.

Saat membuat batas kata, kita harus menggunakan garis miring ganda karena kita menulisnya dalam baris biasa, dan bukan dalam urutan biasa dengan garis miring ke depan. Argumen kedua pada RegExp berisi opsi untuk ekspresi reguler - dalam kasus kami "gi", yaitu. global dan peka huruf besar-kecil.

Namun bagaimana jika namanya “dea+hlrd” (jika pengguna kita adalah seorang kulhatzker)? Hasilnya, kita akan mendapatkan ekspresi reguler yang tidak berarti yang tidak akan menemukan kecocokan dalam string.

Kita dapat menambahkan garis miring terbalik sebelum karakter apa pun yang tidak kita sukai. Kita tidak dapat menambahkan garis miring terbalik sebelum huruf karena \b atau \n adalah karakter khusus. Namun Anda dapat menambahkan garis miring sebelum karakter non-alfanumerik tanpa masalah.

Var nama = "dea+hlrd"; var text = "Dea+hlrd ini mengganggu semua orang."; var lolos = nama.replace(/[^\w\s]/g, "\\$&"); var regexp = RegExp baru("\\b(" + lolos + ")\\b", "gi"); console.log(text.replace(regexp, "_$1_")); // → _dea+hlrd_ ini membuat semua orang kesal.

metode pencarian

Metode indexOf tidak dapat digunakan dengan ekspresi reguler. Namun ada metode pencarian yang hanya mengharapkan ekspresi reguler. Seperti indexOf, ia mengembalikan indeks kemunculan pertama, atau -1 jika tidak ada yang terjadi.

Console.log(" kata".pencarian(/\S/)); // → 2 console.log(" ".search(/\S/)); // → -1

Sayangnya, tidak ada cara untuk memberitahu metode untuk mencari kecocokan yang dimulai pada offset tertentu (seperti yang dapat Anda lakukan dengan indexOf). Itu akan sangat membantu.

properti indeks terakhir

Metode exec juga tidak menyediakan cara mudah untuk memulai pencarian dari posisi tertentu dalam string. Tapi itu memberikan cara yang tidak nyaman.

Objek regex memiliki properti. Salah satunya adalah source yang berisi string. Yang lainnya adalah lastIndex, yang mengontrol, dalam beberapa kondisi, di mana pencarian kejadian berikutnya akan dimulai.

Kondisi ini termasuk opsi global g harus ada, dan pencarian harus dilakukan menggunakan metode exec. Solusi yang lebih masuk akal adalah dengan mengizinkan argumen tambahan diteruskan ke exec, tetapi kewajaran bukanlah fitur mendasar dari antarmuka regex JavaScript.

Pola var = /y/g; pola.lastIndex = 3; var pertandingan = pola.exec("xyzzy"); console.log(match.index); // → 4 console.log(pattern.lastIndex); // → 5

Jika pencarian berhasil, panggilan exec memperbarui properti lastIndex untuk menunjuk ke posisi setelah kejadian yang ditemukan. Jika tidak berhasil, lastIndex disetel ke nol - sama seperti lastIndex dari objek yang baru dibuat.

Saat menggunakan variabel reguler global dan beberapa panggilan exec, pembaruan lastIndex otomatis ini dapat menyebabkan masalah. Server reguler Anda dapat mulai mencari dari posisi kiri dari panggilan sebelumnya.

Var angka = /\d/g; console.log(digit.exec("ini dia: 1")); // → ["1"] console.log(digit.exec("dan ​​sekarang: 1")); // → batal

Efek menarik lainnya dari opsi g adalah mengubah cara kerja metode pencocokan. Saat dipanggil dengan opsi ini, alih-alih mengembalikan larik yang mirip dengan hasil exec, opsi ini akan menemukan semua kemunculan pola dalam string dan mengembalikan larik substring yang ditemukan.

Console.log("Pisang".cocok(/an/g)); // → ["sebuah", "sebuah"]

Jadi berhati-hatilah dengan variabel reguler global. Kasus-kasus di mana mereka diperlukan - ganti panggilan atau tempat di mana Anda secara khusus menggunakan lastIndex - mungkin merupakan semua kasus di mana mereka harus digunakan.

Siklus kejadian

Tugas umumnya adalah mengulangi semua kemunculan pola dalam string sehingga dapat mengakses objek kecocokan di badan perulangan menggunakan lastIndex dan exec.

Var input = "Garis dengan 3 angka di dalamnya... 42 dan 88."; var nomor = /\b(\d+)\b/g; pertandingan var; while (cocok = angka.exec(input)) console.log("Ditemukan", cocok, " pada ", cocok.index); // → Ditemukan 3 kali 14 // Ditemukan 42 kali 33 // Ditemukan 88 kali 40

Ini memanfaatkan fakta bahwa nilai penugasan adalah nilai yang diberikan. Dengan menggunakan match = re.exec(input) sebagai kondisi dalam perulangan while, kita mencari di awal setiap iterasi, menyimpan hasilnya dalam variabel, dan mengakhiri perulangan ketika semua kecocokan ditemukan.

Mengurai file INI

Untuk mengakhiri bab ini, mari kita lihat masalah menggunakan ekspresi reguler. Bayangkan kita sedang menulis sebuah program yang mengumpulkan informasi tentang musuh kita melalui Internet secara otomatis. (Kami tidak akan menulis keseluruhan program, hanya bagian yang membaca file pengaturan. Maaf.) Filenya terlihat seperti ini:

Mesin Pencari=http://www.google.com/search?q=$1 kedengkian=9.7 ; titik koma ditempatkan sebelum komentar; setiap bagian mengacu pada musuh yang berbeda fullname=Larry Doe type=tk bull website=http://www.geocities.com/CapeCanaveral/11451 fullname=Gargamel type=evil wizard outputdir=/home/marijn/enemies/gargamel

Format file sebenarnya (yang cukup banyak digunakan, dan biasa disebut INI) adalah sebagai berikut:

Baris kosong dan baris yang dimulai dengan titik koma diabaikan
- garis yang diapit tanda kurung siku memulai bagian baru
- baris yang berisi pengenal alfanumerik diikuti dengan = tambahkan pengaturan di bagian ini

Yang lainnya adalah data yang salah.

Tugas kita adalah mengubah string tersebut menjadi array objek, masing-masing dengan properti nama dan array pengaturan. Satu objek diperlukan untuk setiap bagian, dan objek lainnya diperlukan untuk pengaturan global di atas file.

Karena file perlu diurai baris demi baris, ada baiknya memulai dengan memecah file menjadi beberapa baris. Untuk melakukan ini, kami menggunakan string.split("\n") di Bab 6. Beberapa sistem operasi tidak menggunakan satu karakter \n untuk jeda baris, namun dua karakter - \r\n. Karena metode split menggunakan ekspresi reguler sebagai argumen, kita dapat memisahkan baris menggunakan ekspresi /\r?\n/, yang memungkinkan \n dan \r\n antar baris.

Fungsi parseINI(string) ( // Mari kita mulai dengan objek yang berisi pengaturan tingkat atas var currentSection = (nama: null, bidang: ); var kategori = ; string.split(/\r?\n/).forEach(function (baris ) ( var pertandingan; if (/^\s*(;.*)?$/.test(line)) ( return; ) else if (pertandingan = baris.pertandingan(/^\[(.*)\ ]$ /)) ( currentSection = (nama: cocok, bidang: ); kategori.push(currentSection); ) else if (cocok = baris.cocok(/^(\w+)=(.*)$/)) ( currentSection.fields.push((nama: cocok, nilai: cocok)); else ( throw new Error("Baris "" + baris + "" berisi data yang tidak valid."); ) ));

var kategori = ;

string.split(/\r?\n/).forEach(function(line) ( var match; if (/^\s*(;.*)?$/.test(line)) ( return; ) else if (cocok = baris.cocok(/^\[(.*)\]$/)) ( currentSection = (nama: cocok, bidang: ); kategori.push(currentSection); ) else if (cocok = baris.cocok( /^(\w+)=(.*)$/)) ( currentSection.fields.push((nama: cocok, nilai: cocok)); ) else ( throw new Error("Baris "" + baris + "" berisi data salah."); ) ));

kategori pengembalian; )

Kode melewati semua baris, memperbarui objek bagian saat ini "bagian saat ini". Pertama, ia memeriksa apakah baris dapat diabaikan menggunakan ekspresi reguler /^\s*(;.*)?$/. Bisakah Anda bayangkan cara kerjanya? Bagian di antara tanda kurung cocok dengan komentar ya? membuatnya agar karakter biasa juga akan cocok dengan garis yang hanya terdiri dari spasi.

Jika baris tersebut bukan komentar, kode akan memeriksa apakah baris tersebut memulai bagian baru. Jika ya, ini akan membuat objek baru untuk bagian saat ini, yang mana pengaturan berikutnya akan ditambahkan.

Kemungkinan terakhir yang berarti adalah bahwa string tersebut merupakan pengaturan normal, dalam hal ini string tersebut ditambahkan ke objek saat ini.

Jika tidak ada opsi yang berfungsi, fungsi akan menimbulkan kesalahan.

Perhatikan bagaimana seringnya penggunaan ^ dan $ memastikan bahwa ekspresi tersebut cocok dengan keseluruhan string, bukan hanya sebagian saja. Jika Anda tidak menggunakannya, kode tersebut secara umum akan berfungsi, tetapi terkadang memberikan hasil yang aneh dan kesalahannya akan sulit dilacak.

Anehnya, secara historis \s (spasi) cocok dengan semua karakter yang dianggap spasi putih di Unicode, termasuk karakter seperti spasi tak putus atau pemisah vokal Mongolia.

Beberapa implementasi regex dalam bahasa lain memiliki sintaks khusus untuk mencari kategori khusus karakter Unicode, seperti "huruf besar semua", "tanda baca semua", atau "karakter kontrol". Ada rencana untuk menambahkan kategori seperti itu ke JavaScript, namun kemungkinan besar tidak akan diterapkan dalam waktu dekat.

Intinya

Regular adalah objek yang mewakili pola pencarian dalam string. Mereka menggunakan sintaksis mereka sendiri untuk mengekspresikan pola-pola ini.

/abc/ Urutan karakter
// Karakter apa pun dari daftar
/[^abc]/ Karakter apa pun kecuali karakter dari daftar
// Karakter apa pun dari interval
/x+/ Satu atau lebih kemunculan pola x
/x+?/ Satu atau lebih kemunculan, tidak serakah
/x*/ Nol atau lebih kemunculan
/x?/ Nol atau satu kejadian
/x(2,4)/ Dari dua hingga empat kemunculan
/(abc)/ Grup
/a|b|c/ Salah satu dari beberapa pola
/\d/ Nomor berapa pun
/\w/ Karakter alfanumerik apa pun (“huruf”)
/\s/ Karakter spasi apa pun
/./ Karakter apa pun kecuali jeda baris
/\b/ Batas kata
/^/ Awal baris
/$/ Akhir baris

Regex memiliki metode pengujian untuk memeriksa apakah polanya ada dalam string. Ada metode exec yang mengembalikan array yang berisi semua grup yang ditemukan. Array memiliki properti indeks, yang berisi jumlah karakter asal kecocokan.

String memiliki metode pencocokan untuk mencocokkan pola, dan metode pencarian yang hanya mengembalikan posisi awal kemunculannya. Metode ganti dapat mengganti kemunculan suatu pola dengan string lain. Selain itu, Anda dapat meneruskan fungsi pengganti yang akan membuat baris pengganti berdasarkan templat dan grup yang ditemukan.

Karakter biasa memiliki pengaturan yang ditulis setelah garis miring penutup. Opsi i menjadikan ekspresi reguler tidak peka huruf besar-kecil, dan opsi g menjadikannya global, yang, antara lain, menyebabkan metode replace menggantikan semua kemunculan yang ditemukan, bukan hanya yang pertama.

Konstruktor RegExp dapat digunakan untuk membuat ekspresi reguler dari string.

Regulator adalah instrumen tajam dengan pegangan yang tidak nyaman. Mereka sangat menyederhanakan beberapa tugas, dan bisa menjadi tidak terkendali ketika memecahkan masalah lain yang kompleks. Bagian dari belajar menggunakan regex adalah untuk mampu menahan godaan untuk mengisinya dengan tugas yang tidak dimaksudkan.

Latihan

Tak pelak lagi, saat memecahkan masalah, Anda akan menghadapi kasus-kasus yang tidak dapat dipahami, dan terkadang Anda mungkin putus asa ketika melihat perilaku beberapa ekspresi reguler yang tidak dapat diprediksi. Terkadang mempelajari perilaku mesin biasa melalui layanan online seperti debuggex.com membantu, di mana Anda dapat melihat visualisasinya dan membandingkannya dengan efek yang diinginkan.
Golf biasa
“Golf” dalam kode adalah permainan di mana Anda perlu mengekspresikan program tertentu dalam jumlah karakter minimum. Golf reguler adalah latihan praktis dalam menulis angka tetap sekecil mungkin untuk menemukan pola tertentu, dan hanya itu.

Untuk setiap subbaris, tulis ekspresi reguler untuk memeriksa lokasinya di baris. Mesin reguler seharusnya hanya menemukan substring tertentu ini. Jangan khawatir tentang batasan kata kecuali disebutkan secara khusus. Jika Anda memiliki pola kerja teratur, cobalah menguranginya.

Mobil dan kucing
- pop dan penyangga
- musang, feri, dan ferrari
- Kata apa pun yang berakhiran ious
- Spasi diikuti titik, koma, titik dua, atau titik koma.
- Sebuah kata yang panjangnya lebih dari enam huruf
- Kata tanpa huruf e

// Masukkan ekspresi reguler verifikasi(/.../, ["mobil saya", "kucing nakal"], ["camper", "seni tinggi"]); verifikasi(/.../, ["budaya pop", "alat peraga gila"], ["plop"]); verifikasi(/.../, ["musang", "feri", "ferrari"], ["ferrum", "transfer A"]); verifikasi(/.../, ["betapa enak", "ruangan luas"], ["merusak", "kesadaran"]); verifikasi(/.../, ["tanda baca buruk ."], ["escape the dot"]); verifikasi(/.../, ["hottenottententen"], ["tidak", "hotten totten tenten"]); verifikasi(/.../, ["platipus merah", "sarang goyangan"], ["alas tanah", "kera belajar"]); function verifikasi(regexp, yes, no) ( // Abaikan latihan yang belum selesai if (regexp.source == "...") return; yes.forEach(function(s) ( if (!regexp.test(s)) console .log("Tidak ditemukan "" + s + """ )); no.forEach(function(s) ( if (regexp.test(s)) console.log("Kejadian tak terduga "" + s + " "" );

Kutipan dalam teks
Katakanlah Anda menulis sebuah cerita dan menggunakan tanda kutip tunggal untuk menunjukkan dialog. Sekarang Anda ingin mengganti tanda kutip dialog dengan tanda kutip ganda, dan membiarkan tanda kutip tunggal dalam singkatan untuk kata-kata seperti bukan.

Buatlah pola yang membedakan kedua penggunaan tanda kutip ini, dan tuliskan panggilan ke metode penggantian yang melakukan penggantian.

Angka lagi
Urutan angka dapat ditemukan dengan ekspresi reguler sederhana /\d+/.

Tulis ekspresi yang hanya menemukan angka yang ditulis dalam gaya JavaScript. Itu harus mendukung kemungkinan minus atau plus sebelum angka, titik desimal, dan notasi ilmiah 5e-3 atau 1E10 - sekali lagi dengan kemungkinan plus atau minus. Perhatikan juga bahwa belum tentu ada angka sebelum atau sesudah titik, tetapi angka tersebut tidak boleh terdiri dari satu titik. Artinya, 0,5 atau 5 adalah bilangan valid, namun satu titik saja bukan bilangan valid.

// Masukkan urutan reguler di sini. var nomor = /^...$/; // Pengujian: ["1", "-1", "+15", "1.55", ".5", "5.", "1.3e2", "1E-4", "1e+12"] .forEach(function(s) ( if (!number.test(s)) console.log("Tidak menemukan "" + s + """); )); ["1a", "+-1", "1.2.3", "1+1", "1e4.5", ".5.", "1f5", "."].forEach(fungsi) ( if (number.test(s)) console.log("Salah diterima "" + s + """); ));

Dalam JavaScript, ekspresi reguler diwakili oleh objek RegExp. Objek RegExp dapat dibuat menggunakan konstruktor RegExp(), namun lebih sering objek tersebut dibuat menggunakan sintaks literal khusus. Sama seperti literal string yang ditentukan sebagai karakter yang diapit tanda kutip, literal ekspresi reguler ditentukan sebagai karakter yang diapit oleh pasangan garis miring / .

/pattern/flags RegExp baru("pola"[, opsi pencarian])

pola- ekspresi reguler untuk pencarian (lebih lanjut tentang penggantian nanti), dan flag - string dari kombinasi karakter apa pun g (pencarian global), i (huruf besar tidak penting) dan m (pencarian multi-baris). Metode pertama sering digunakan, metode kedua kadang-kadang. Misalnya, dua panggilan tersebut setara.

Opsi pencarian

Saat membuat ekspresi reguler, kita dapat menentukan opsi pencarian tambahan

Karakter dalam Ekspresi Reguler JavaScript

SimbolKorespondensi
Karakter alfanumerikSesuai dengan diri mereka sendiri
\0 karakter NUL (\u0000)
\TTab (\u0009)
\NUmpan baris (\u000A)
\vTab vertikal (\u000B)
\FTerjemahan halaman (\u000C)
\RPengembalian kereta (\u000D)
\xnnKumpulan karakter Latin angka heksadesimal nn; misalnya \x0A sama dengan \n
\uxxxxKarakter unicode ditentukan oleh angka heksadesimal xxxx; misalnya, \u0009 sama dengan \t
\cXKarakter kontrol "X", misalnya, urutan \cJ setara dengan karakter baris baru \n
\ Untuk karakter biasa - menjadikannya istimewa. Misalnya, ekspresi /s/ hanya mencari karakter "s". Dan jika Anda meletakkan \ sebelum s, maka /\s/ sudah melambangkan karakter spasi, dan sebaliknya, jika karakternya khusus, misalnya *, maka \ akan menjadikannya hanya karakter “tanda bintang” biasa. Misalnya, /a*/ mencari 0 atau lebih karakter "a" yang berurutan. Untuk menemukan a dengan tanda bintang "a*" - letakkan \ di depan yang spesial. simbol: /a\*/ .
^ Menunjukkan awal dari data masukan. Jika tanda pencarian multibaris ("m") disetel, ia juga akan aktif di awal baris baru. Misalnya, /^A/ tidak akan menemukan "A" di "an A", namun akan menemukan yang pertama "A" dalam "Sebuah A."
$ Menunjukkan akhir dari data masukan. Jika tanda pencarian multibaris disetel, ini juga akan berfungsi di akhir baris. Misalnya, /t$/ tidak akan menemukan "t" di "eater", tetapi akan menemukannya di "eat".
* Menunjukkan pengulangan 0 kali atau lebih. Misalnya, /bo*/ akan menemukan "boooo" di "A ghost booooed" dan "b" di "A bird warbled", namun tidak akan menemukan apa pun di "A kambing mendengus".
+ Menunjukkan pengulangan 1 kali atau lebih. Setara dengan (1,). Misalnya, /a+/ akan cocok dengan "a" di "permen" dan semua "a" di "caaaaaaandy".
? Menunjukkan bahwa elemen tersebut mungkin ada atau tidak. Misalnya, /e?le?/ akan cocok dengan "el" di "angel" dan "le" di "angle". Jika digunakan tepat setelah salah satu bilangan * , + , ? , atau () , kemudian menentukan pencarian "non-serakah" (mengulangi jumlah minimum yang mungkin, ke elemen terdekat berikutnya dari pola), sebagai lawan dari mode "serakah" default, di mana jumlah pengulangan adalah maksimal, meskipun elemen berikutnya polanya juga cocok. digunakan dalam pratinjau, yang dijelaskan dalam tabel di bawah (?=) , (?!) , dan (?:) .
. (Titik desimal) mewakili karakter apa pun selain baris baru: \n \r \u2028 atau \u2029. (Anda dapat menggunakan [\s\S] untuk mencari karakter apa pun, termasuk baris baru). Misalnya, /.n/ akan cocok dengan "an" dan "on" dalam "tidak, ada apel di pohon", tetapi tidak "tidak".
(X)Menemukan x dan mengingatnya. Ini disebut "kurung memori". Misalnya, /(foo)/ akan menemukan dan mengingat "foo" di "foo bar". Substring yang ditemukan disimpan dalam larik hasil pencarian atau dalam properti objek RegExp yang telah ditentukan sebelumnya: $1, ..., $9. Selain itu, tanda kurung menggabungkan apa yang terkandung di dalamnya menjadi satu elemen pola. Misalnya, (abc)* - ulangi abc 0 kali atau lebih.
(?:X)Menemukan x, tetapi tidak mengingat apa yang ditemukannya. Ini disebut "tanda kurung memori". Substring yang ditemukan tidak disimpan dalam larik hasil dan properti RegExp. Seperti semua tanda kurung, substring tersebut menggabungkan apa yang ada di dalamnya menjadi satu subpola.
x(?=kamu)Menemukan x hanya jika x diikuti oleh y. Misalnya, /Jack(?=Sprat)/ hanya akan cocok dengan "Jack" jika diikuti dengan "Sprat". /Jack(?=Sprat|Frost)/ hanya akan cocok dengan "Jack" jika diikuti dengan "Sprat" atau "Frost". Namun, baik "Sprat" maupun "Frost" tidak akan muncul di hasil pencarian.
x(?!y)Menemukan x hanya jika x tidak diikuti oleh y. Misalnya, /\d+(?!\.)/ hanya akan mencocokkan angka jika tidak diikuti dengan koma desimal. /\d+(?!\.)/.exec("3.141") akan menemukan 141, tetapi tidak 3.141.
x|yMenemukan x atau y. Misalnya, /green|red/ akan cocok dengan "hijau" di "apel hijau" dan "merah" di "apel merah".
(N)Dimana n adalah bilangan bulat positif. Menemukan tepat n pengulangan elemen sebelumnya. Misalnya, /a(2)/ tidak akan menemukan "a" dalam "candy", namun akan menemukan kedua a dalam "caandy", dan dua a pertama dalam "caaandy".
(N,)Dimana n adalah bilangan bulat positif. Menemukan n atau lebih pengulangan suatu elemen. Misalnya, /a(2,) tidak akan menemukan "a" di "permen", namun akan menemukan semua "a" di "caandy" dan di "caaaaaaandy".
(n,m)Dimana n dan m adalah bilangan bulat positif. Temukan dari n hingga m pengulangan elemen.
Kumpulan karakter. Menemukan salah satu karakter yang terdaftar. Anda dapat menunjukkan spasi dengan menggunakan tanda hubung. Misalnya, - sama dengan . Cocok dengan "b" dalam "brisket" dan "a" dan "c" dalam "ache".
[^xyz]Karakter apa pun selain yang ditentukan dalam set. Anda juga dapat menentukan rentang. Misalnya, [^abc] sama dengan [^a-c] . Temukan "r" di "brisket" dan "h" di "chop".
[\B]Menemukan karakter spasi mundur. (Jangan bingung dengan \b .)
\BMenemukan batas kata (Latin), seperti spasi. (Jangan bingung dengan [\b]). Misalnya, /\bn\w/ akan cocok dengan "no" di "noonday"; /\wy\b/ akan menemukan "ly" di "mungkin kemarin."
\BItu tidak menunjukkan batasan kata. Misalnya, /\w\Bn/ akan cocok dengan "on" di "noonday", dan /y\B\w/ akan cocok dengan "ye" di "mungkin kemarin".
\cXDimana X adalah huruf dari A sampai Z. Menunjukkan karakter kontrol dalam sebuah string. Misalnya, /\cM/ mewakili karakter Ctrl-M.
\Dmenemukan nomor dari alfabet apa pun (milik kami adalah Unicode). Gunakan untuk menemukan angka biasa saja. Misalnya, /\d/ atau // akan cocok dengan "2" di "B2 adalah nomor suite".
\DMenemukan karakter non-numerik (semua huruf). [^0-9] setara dengan bilangan biasa. Misalnya, /\D/ atau /[^0-9]/ akan cocok dengan "B" di "B2 adalah nomor suite."
\SMenemukan karakter spasi apa pun, termasuk spasi, tab, baris baru, dan karakter spasi Unicode lainnya. Misalnya, /\s\w*/ akan cocok dengan "bar" di "foo bar."
\SMenemukan karakter apa pun kecuali spasi. Misalnya, /\S\w*/ akan cocok dengan "foo" di "foo bar".
\vKarakter tab vertikal.
\wMenemukan karakter kata apa pun (abjad Latin), termasuk huruf, angka, dan garis bawah. Setara. Misalnya, /\w/ akan cocok dengan "a" di "apple", "5" di "$5,28", dan "3" di "3D".
\WMenemukan karakter verbal non-(Latin). Setara dengan [^A-Za-z0-9_] . Misalnya, /\W/ dan /[^$A-Za-z0-9_]/ akan sama-sama cocok dengan "%" di "50%."

Bekerja dengan Ekspresi Reguler dalam Javascript

Bekerja dengan ekspresi reguler dalam Javascript diimplementasikan menggunakan metode kelas String

exec(regexp) - menemukan semua kecocokan (entri dalam pola reguler) dalam sebuah string. Mengembalikan array (jika ada yang cocok) dan memperbarui properti regexp, atau null jika tidak ada yang ditemukan. Dengan pengubah g - setiap kali fungsi ini dipanggil, fungsi ini akan mengembalikan kecocokan berikutnya setelah kecocokan sebelumnya ditemukan - ini diterapkan dengan mempertahankan indeks offset dari pencarian terakhir.

match(regexp) - temukan bagian dari string menggunakan suatu pola. Jika pengubah g ditentukan, match() akan mengembalikan array yang berisi semua kecocokan atau null (bukan array kosong). Tanpa pengubah g, fungsi ini berfungsi seperti exec();

test(regexp) - fungsi memeriksa string untuk mencocokkan suatu pola. Mengembalikan nilai benar jika ada kecocokan, dan salah jika tidak ada kecocokan.

split(regexp) - Membagi string yang dipanggil menjadi array substring, menggunakan argumen sebagai pembatas.

replace(regexp, mix) - metode mengembalikan string yang dimodifikasi sesuai dengan template (ekspresi reguler). Parameter pertama untuk regexp juga bisa berupa string, bukan ekspresi reguler. Tanpa pengubah g, metode pada baris hanya menggantikan kemunculan pertama; dengan pengubah g - terjadi penggantian global, mis. semua kejadian di baris tertentu diubah.

mix - template pengganti, dapat menerima nilai string, template pengganti, fungsi (nama fungsi).

Karakter khusus dalam string pengganti

Penggantian melalui fungsi

  • Jika Anda menentukan suatu fungsi sebagai parameter kedua, fungsi tersebut akan dijalankan untuk setiap kecocokan. Suatu fungsi dapat secara dinamis menghasilkan dan mengembalikan string substitusi. Parameter pertama dari fungsi ini adalah substring yang ditemukan. Jika argumen pertama yang harus diganti adalah objek RegExp, maka n parameter berikutnya berisi tanda kurung yang cocok. Dua parameter terakhir adalah posisi pada garis dimana pertandingan terjadi dan garis itu sendiri.

    semacam ulasan "pendek"... seolah-olah mereka sedang terburu-buru di suatu tempat