Чому діапазон [01-12] не працює належним чином?


91

Я намагаюся використовувати шаблон діапазону [01-12]в регулярному виразі, щоб відповідати двоцифровим мм, але це не працює належним чином.


8
Ви відповідаєте символам , а не послідовностям символів . В основному, ви відповідаєте 0, 1 до 1 і 2 (тобто 0, 1 і 2). Розглянемо це:, [a-z0-9]це відповідає всій малій літери та всім цифрам, але лише як один символ.
Лассе В. Карлсен,

fwiw Я створив інструмент javascript, який створює високооптимізований регулярний вираз із двох входів (хв. / макс.) github.com/jonschlinkert/to-regex-range
jonschlinkert

0 [1-9] | 1 [0-2] -> 0 | 1 | 2 -> [] в регулярному виразі позначають клас символів. Якщо не вказано жодного діапазону, це неявно встановлює кожен символ.
Badri Gs

Вам потрібно поєднувати його з чистими регулярними виразами? Якщо ні, ви можете: 1.) просто використати \d+шаблон, 2.) перетворити відповідні рядки на цифри у коді. а потім, 3.) перевірте діапазон чисел, наприклад if(num >= 0 && num <= 12){ /*do something*/ }. Це набагато швидше та гнучкіше.
acegs

Відповіді:


192

Здається, ви неправильно зрозуміли, як працює визначення класів символів у регулярному виразі.

Для того, щоб відповідати кожному з рядків 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, або 12, що - щось на зразок цього твору:

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

Список літератури


Пояснення

Клас символів сам по собі намагається зіставити один і рівно один символ із вхідного рядка. [01-12]на самому ділі визначає [012], клас персонажа , який відповідає одному символу з вхідного проти будь-якого з 3 -х символів 0, 1або 2.

Визначення -діапазону йде від 1до 1, що включає просто 1. З іншого боку, що - щось на зразок [1-9]включає в себе 1, 2, 3, 4, 5, 6, 7, 8, 9.

Новачки часто роблять помилки, визначаючи такі речі [this|that]. Це не "працює". Цей символ визначає визначення [this|a], тобто він відповідає одному символу з вхідних проти будь-якого з 6 символів t, h, i, s, |або a. Більш ніж ймовірно (this|that), що це задумано.

Список літератури


Як визначаються діапазони

Тож очевидно, що такий шаблон between [24-48] hoursне працює. Клас символів у цьому випадку еквівалентний [248].

Тобто, -у визначенні класу символів не визначається числовий діапазон у шаблоні. Системи регулярних виразів насправді не «розуміють» числа в шаблоні, за винятком синтаксису кінцевих повторень (наприклад, a{3,5}збіги між 3 і 5 a).

Визначення діапазону замість цього використовує кодування ASCII / Unicode символів для визначення діапазонів. Символ 0кодується в ASCII як десятковий 48; 9дорівнює 57. Таким чином, визначення символу [0-9]включає всі символи, значення яких знаходяться між десятковими 48 і 57 в кодуванні. Швидше здраво, дизайн ці символи 0, 1, ..., 9.

Дивитися також


Інший приклад: від А до Я

Давайте подивимось на інше поширене визначення класу символів [a-zA-Z]

У ASCII:

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

Це означає що:

  • [a-zA-Z]і [A-Za-z]еквівалентні
  • У більшості ароматів, [a-Z]ймовірно, це нелегальний діапазон символів
    • тому що a(97) "більше" ніж Z(90)
  • [A-z] є законним, але також включає ці шість символів:
    • [(91), \(92), ](93), ^(94), _(95), `(96)

Пов’язані запитання


Для мене я шукав місяці без префікса 0, якщо однозначний. І я використовував це ([1-9] | (1 [0-2])), і це працює.
bunjeeb

2
Важливо: зауважте, що якщо ви знайдете цю сторінку, яка шукає рішення для вашого діапазону чисел, яке має лише одноцифрові цифри, перш ніж дістатися до десятків, 0[1-9]|1[0-2]це не спрацює. Зміна його на наступний логічний крок [1-9]|1[0-2]не працює або зі зрозумілих причин (він збігається з 1тільки 10, 11і 12). Довелося використовувати, \b(?:[0-9]|1[0-1])\bщоб запобігти цьому. \b's переконуєсь, що регулярний вираз відповідає межам слова (або, в даному випадку, числа), меж ( ^& $ні); дужки змушують або ( |) розглядати іншу його сторону; і, нарешті, ?:це не створювати підрахування за допомогою дужок.
user66001

@polygenelubricants: "1,2,3,4,5,6,7,8,9,10,17,18".match(/^(([1-9]|1[0-7])\,?)+$/g )Скажіть, будь ласка, чому цей регулярний вираз JS відповідає вище 17?
Едам,

@edam - polygenelubricants міг, і тому я міг, але тоді ми будемо відповідати на questi ... Зачекайте ... є чи це питання ви задаєте в коментар ? На цьому сайті є rulez ;) Поставте запитання, якщо у вас є нове запитання. Коментарі призначені лише для критики та прохання пояснити, а також для відповіді на них.
robinCTS

1
@edam О, розумію. Ви ж повторно поставити його як питання годину пізніше. Це чудово! Однак, мабуть, було б непогано видалити свій коментар тут.
robinCTS 13.03.18

24

Клас символів у регулярних виразах, позначений [...]синтаксисом, визначає правила, що відповідають одному символу у введенні. Таким чином, усе, що ви пишете в дужках, вказує, як зіставити один символ .

[01-12]Таким чином, ваш шаблон розбивається таким чином:

  • 0 - відповідає одноцифровому 0
  • або, 1-1, відповідає одній цифрі в діапазоні від 1 до 1
  • або, 2, відповідає однозначній цифрі 2

Отже, в основному все, що вам підходить, це 0, 1 або 2.

Для того, щоб виконати відповідність, яку ви хочете, зіставивши дві цифри, починаючи від 01-12 як цифри, вам слід подумати про те, як вони будуть виглядати як текст.

Ти маєш:

  • 01-09 (тобто перша цифра 0, друга цифра 1-9)
  • 10-12 (тобто. Перша цифра - 1, друга цифра - 0-2)

Потім вам доведеться написати регулярний вираз для цього, який може виглядати так:

  +-- 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

Зверніть увагу, що спроба їх поєднати, щоб отримати коротший вираз, не вдасться, давши помилково позитивні збіги для недійсного вводу.

Наприклад, шаблон [0-1][0-9]в основному буде відповідати цифрам 00-19, що трохи більше, ніж ви хочете.

Я спробував знайти певне джерело для отримання додаткової інформації про класи символів, але наразі все, що я можу вам надати, це цей запит Google для класів символів Regex . Сподіваємось, ви зможете знайти там додаткову інформацію, яка допоможе вам.


9

Це також працює:

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

[1-9] відповідає одноцифровим цифрам від 1 до 9

[0-1][0-2] відповідає двоцифровим цифрам від 10 до 12

Є кілька прикладів хороших тут


2
Точніше, [0-1][0-2]також збіги 00. Тим не менше, +1 за посилання (яке я використав у своїй відповіді).
полігенмастильні речовини

2
[0-1][0-2]має бути ретельно інтерпретувати, так як вона дозволяє рядку подобається 00, 01і 02, але він не допускає 03до 09, визнавши , нарешті 10, 11і 12. Правильним регулярним виразом для цього є [1-9]|1[0-2], або навіть 0*([1-9]|1[0-2])(це останнє дозволяє будь-яку кількість провідних нулів).
Луїс Колорадо,

1

В []s в регулярних виразах позначають клас символів . Якщо не вказано жодного діапазону, це неявно або s кожен символ у ньому разом. Таким чином, [abcde]це те саме (a|b|c|d|e), що за винятком того, що воно нічого не фіксує; він буде відповідати будь-якому з a, b, c, d, або e. Весь діапазон вказує набір символів ; [ac-eg]говорить "відповідати будь-якому з a:; будь-якому символу між cі e; або g". Таким чином, у вашому збігу написано: "збігатись із будь-яким із 0:; будь-якого символу між 1і 1( тобто , просто 1); або 2.

Очевидно, що ваша мета - вказати діапазон чисел: будь-яке число між 01і 12записане двома цифрами. У цьому конкретному випадку ви можете зіставити його з 0[1-9]|1[0-2]: або за 0яким слід будь-яка цифра між 1і 9, або 1за будь-якою цифрою між 0і 2. Загалом, ви можете перетворити будь-який діапазон чисел у дійсний регулярний вираз подібним чином. Однак може бути кращий варіант, ніж регулярні вирази, або існуюча функція або модуль, які можуть побудувати регулярний вираз для вас. Це залежить від вашої мови.


0

Як зазначає polygenelubricants, ваші шукатимуть 0 | 1-1 | 2, а не те, що ви бажаєте, через те, що класи символів (речі в []) відповідають символам, а не рядкам.


3
0|1-1|2- це позначення дуже оманливе. Щось подібне 0|1|2було б точнішим.
полігенмастильні речовини

0

Використовуй це:

0?[1-9]|1[012]
  • 07: дійсний
  • 7: дійсний
  • 0: не збігається
  • 00: не збігається
  • 13: не збігається
  • 21: не збігається

Щоб перевірити зразок як 07/2018, використовуйте це:

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

(Діапазон дат між 01/2000 і 12/9999)


Я намагався зрозуміти, як це зробити, але отримати третю умову лише 0, щоб пройти.
mkaatman
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.