Mengapa rentang [01-12] tidak berfungsi seperti yang diharapkan?

93

Saya mencoba menggunakan pola rentang [01-12]dalam ekspresi reguler untuk mencocokkan dua digit mm, tetapi ini tidak berfungsi seperti yang diharapkan.

DEACTIVATIONPRESCRIPTION.NET
sumber
9
Anda mencocokkan karakter , bukan urutan karakter . Pada dasarnya, Anda mencocokkan dengan 0, 1 banding 1, dan 2 (mis. 0, 1 dan 2). Pertimbangkan ini:, ini [a-z0-9]cocok dengan semua huruf kecil, dan semua angka, tetapi hanya sebagai satu karakter.
Lasse V. Karlsen
fwiw Saya membuat alat javascript yang membuat regex yang sangat dioptimalkan dari dua input (min / max) github.com/jonschlinkert/to-regex-range
jonschlinkert
0 [1-9] | 1 [0-2] -> 0 | 1 | 2 -> [] s dalam regex menunjukkan kelas karakter. Jika tidak ada rentang yang ditentukan, itu secara implisit atau setiap karakter.
Badri Gs
Apakah Anda perlu mencocokkannya dengan regex murni? Jika tidak, Anda dapat: 1.) cukup menggunakan \d+pola, 2.) mengonversi string yang cocok menjadi angka dalam kode Anda. dan kemudian, 3.) periksa kisaran angka seperti if(num >= 0 && num <= 12){ /*do something*/ }. Jauh lebih cepat dan fleksibel.
acegs

Jawaban:

198

Anda sepertinya salah paham tentang cara kerja definisi kelas karakter di regex.

Untuk cocok dengan string 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, atau 12, seperti karya-karya ini:

0[1-9]|1[0-2]

Referensi


Penjelasan

Kelas karakter, dengan sendirinya, mencoba mencocokkan satu dan tepat satu karakter dari string input. [01-12]benar-benar mendefinisikan [012], kelas karakter yang cocok dengan satu karakter dari input terhadap salah satu dari 3 karakter 0, 1atau 2.

The -Definisi kisaran pergi dari 1ke 1, yang mencakup hanya 1. Di sisi lain, sesuatu seperti [1-9]meliputi 1, 2, 3, 4, 5, 6, 7, 8, 9.

Para pemula sering membuat kesalahan dalam mendefinisikan hal-hal seperti [this|that]. Ini tidak "berhasil". Karakter ini mendefinisikan definisi [this|a], yaitu cocok satu karakter dari input terhadap setiap 6 karakter di t, h, i, s, |atau a. Kemungkinan besar (this|that)itulah yang dimaksudkan.

Referensi


Bagaimana rentang ditentukan

Jadi sekarang jelas bahwa pola suka between [24-48] hourstidak "berhasil". Kelas karakter dalam kasus ini sama dengan [248].

Artinya, -dalam definisi kelas karakter tidak mendefinisikan rentang numerik dalam pola. Mesin regex tidak benar-benar "memahami" angka dalam pola, dengan pengecualian sintaks pengulangan hingga (misalnya, a{3,5}cocok antara 3 dan 5 a).

Definisi rentang malah menggunakan pengkodean karakter ASCII / Unicode untuk menentukan rentang. Karakter 0dikodekan dalam ASCII sebagai desimal 48; 9adalah 57. Jadi, definisi karakter [0-9]mencakup semua karakter yang nilainya antara desimal 48 dan 57 dalam pengkodean. Sebaliknya bijaksana, dengan desain ini adalah karakter 0, 1..., 9.

Lihat juga


Contoh lain: A sampai Z

Mari kita lihat definisi kelas karakter umum lainnya [a-zA-Z]

Di ASCII:

  • A= 65, Z= 90
  • a= 97, z= 122

Artinya:

  • [a-zA-Z]dan [A-Za-z]setara
  • Dalam kebanyakan rasa, [a-Z]kemungkinan merupakan rentang karakter ilegal
    • karena a(97) "lebih besar dari" dari Z(90)
  • [A-z] legal, tetapi juga mencakup enam karakter berikut:
    • [(91), \(92), ](93), ^(94), _(95), `(96)

Pertanyaan-pertanyaan Terkait

poligenelubricants
sumber
Bagi saya, saya mencari berbulan-bulan tanpa awalan dengan 0 jika satu digit. Dan saya menggunakan ini ([1-9] | (1 [0-2])) dan berhasil.
bunjeeb
3
Penting untuk diperhatikan: Jika Anda merasa halaman ini menginginkan solusi untuk rentang nomor Anda yang hanya memiliki satu digit sebelum mencapai puluhan, 0[1-9]|1[0-2]tidak akan berfungsi. Mengubah ke langkah logis berikutnya [1-9]|1[0-2]tidak bekerja baik untuk alasan dimengerti (Ini sesuai dengan 1hanya dalam 10, 11dan 12). Harus digunakan \b(?:[0-9]|1[0-1])\buntuk mencegahnya. \bpastikan regex cocok dengan kata (atau dalam hal ini angka) batas ( ^& $tidak); tanda kurung membuat atau ( |) mempertimbangkan sisi lain; dan akhirnya ?:adalah tidak membuat submatch dengan menggunakan tanda kurung.
pengguna66001
@ polygenelubricants: "1,2,3,4,5,6,7,8,9,10,17,18".match(/^(([1-9]|1[0-7])\,?)+$/g )Bisakah Anda memberi tahu saya mengapa regex JS ini cocok dengan di atas 17?
edam
@edam - polygenelubricants bisa, dan saya juga bisa, tapi kemudian kami akan menjawab sebuah questi … tunggu… apakah ini pertanyaan yang Anda tanyakan di komentar ? Ada rulez di situs ini;) Ajukan Pertanyaan jika Anda memiliki pertanyaan baru. Komentar hanya untuk mengkritik dan meminta klarifikasi, dan untuk menanggapi itu.
robinCTS
1
@edam Oh, begitu. Anda memang menanyakannya kembali satu jam kemudian. Itu hebat! Namun, mungkin ada baiknya untuk menghapus komentar Anda di sini.
robinCTS
24

Kelas karakter dalam ekspresi reguler, dilambangkan dengan [...]sintaksis, menetapkan aturan untuk mencocokkan satu karakter dalam input. Dengan demikian, semua yang Anda tulis di antara tanda kurung menentukan cara mencocokkan satu karakter .

[01-12]Dengan demikian , pola Anda dipecah sebagai berikut:

  • 0 - cocok dengan satu digit 0
  • atau, 1-1, cocokkan satu digit dalam rentang 1 sampai 1
  • atau, 2, cocokkan satu digit 2

Jadi pada dasarnya semua yang Anda cocokkan adalah 0, 1 atau 2.

Untuk melakukan pencocokan yang Anda inginkan, mencocokkan dua digit, mulai dari 01-12 sebagai angka, Anda perlu memikirkan bagaimana tampilannya sebagai teks.

Kamu punya:

  • 01-09 (misalnya digit pertama adalah 0, digit kedua adalah 1-9)
  • 10-12 (mis. Digit pertama adalah 1, digit kedua adalah 0-2)

Anda kemudian harus menulis ekspresi reguler untuk itu, yang akan terlihat seperti ini:

  +-- a 0 followed by 1-9
  |
  |      +-- a 1 followed by 0-2
  |      |
<-+--> <-+-->
0[1-9]|1[0-2]
      ^
      |
      +-- vertical bar, this roughly means "OR" in this context

Perhatikan bahwa mencoba menggabungkan keduanya untuk mendapatkan ekspresi yang lebih pendek akan gagal, dengan memberikan kecocokan positif palsu untuk masukan yang tidak valid.

Misalnya, pola [0-1][0-9]pada dasarnya akan cocok dengan angka 00-19, yang sedikit lebih banyak dari yang Anda inginkan.

Saya mencoba menemukan sumber yang pasti untuk informasi lebih lanjut tentang kelas karakter, tetapi untuk sekarang yang dapat saya berikan kepada Anda hanyalah Google Query untuk Kelas Karakter Regex . Semoga Anda dapat menemukan lebih banyak informasi di sana untuk membantu Anda.

Lasse V. Karlsen
sumber
9

Ini juga berfungsi:

^([1-9]|[0-1][0-2])$

[1-9] cocok dengan satu digit antara 1 dan 9

[0-1][0-2] cocok dengan dua digit antara 10 dan 12

Ada beberapa contoh bagus di sini

codingbadger
sumber
2
Tepatnya, [0-1][0-2]juga cocok 00. Yang mengatakan, +1 untuk tautan (yang telah saya gunakan dalam jawaban saya).
poligenelubricants
2
[0-1][0-2]harus hati-hati ditafsirkan, karena memungkinkan string seperti 00, 01, dan 02, tetapi tidak mengakui 03sampai 09, mengakui akhirnya 10, 11dan 12. Regex yang tepat untuk itu [1-9]|1[0-2], atau bahkan 0*([1-9]|1[0-2])(yang terakhir ini mengizinkan sejumlah nol di depan).
Luis Colorado
1

Huruf []s dalam regex menunjukkan kelas karakter . Jika tidak ada rentang yang ditentukan, itu secara implisit atau setiap karakter di dalamnya bersama-sama. Jadi, [abcde]adalah sama dengan (a|b|c|d|e), kecuali bahwa ia tidak menangkap apapun; akan cocok salah satu dari a, b, c, d, atau e. Semua rentang menunjukkan adalah sekumpulan karakter ; [ac-eg]mengatakan "cocok dengan salah satu dari a:; karakter apa pun antara cdan e; atau g". Jadi, pencocokan Anda mengatakan "cocok dengan salah satu dari 0:; karakter apa pun antara 1dan 1( yaitu , hanya 1); atau 2.

Tujuan Anda jelas untuk menentukan rentang angka: angka apa pun di antara 01dan 12ditulis dengan dua digit. Dalam kasus khusus ini, Anda dapat mencocokkannya dengan 0[1-9]|1[0-2]: baik 0diikuti dengan digit antara 1dan 9, atau 1diikuti dengan digit antara 0dan 2. Secara umum, Anda dapat mengubah rentang angka apa pun menjadi ekspresi reguler yang valid dengan cara yang serupa. Akan tetapi, mungkin ada opsi yang lebih baik daripada ekspresi reguler, atau fungsi atau modul yang sudah ada yang dapat membuat ekspresi reguler untuk Anda. Itu tergantung pada bahasa Anda.

Antal Spector-Zabusky
sumber
0

Seperti yang dikatakan pelumas poligen, milik Anda akan mencari 0 | 1-1 | 2 daripada yang Anda inginkan, karena fakta bahwa kelas karakter (hal dalam []) cocok dengan karakter daripada string.

fbstj
sumber
3
0|1-1|2- notasi ini sangat menyesatkan. Sesuatu seperti 0|1|2itu akan lebih akurat.
poligenelubricants
0

Gunakan ini:

0?[1-9]|1[012]
  • 07: valid
  • 7: valid
  • 0: tidak cocok
  • 00: tidak cocok
  • 13: tidak cocok
  • 21: tidak cocok

Untuk menguji pola sebagai 07/2018 gunakan ini:

/^(0?[1-9]|1[012])\/([2-9][0-9]{3})$/

(Rentang tanggal antara 01/2000 hingga 12/9999)

Eolia
sumber
Saya sudah mencoba mencari cara untuk melakukan ini tetapi untuk mendapatkan kondisi ketiga hanya 0 untuk lulus.
mkaatman