Почему диапазон [01-12] не работает должным образом?


93

Я пытаюсь использовать шаблон диапазона [01-12]в регулярном выражении для соответствия двузначным мм, но это работает не так, как ожидалось.


9
Вы сопоставляете символы , а не последовательности символов . По сути, вы сопоставляете 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

Ответы:


198

Вы, кажется, неправильно поняли, как определение классов символов работает в регулярном выражении.

Для того, чтобы соответствовать любой из строк 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

3
Важное примечание: если вы обнаружите, что на этой странице требуется решение для вашего диапазона номеров, в котором только однозначные цифры, прежде чем переходить к десяткам, 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

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

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

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 за ссылку (которую я использовал в своем ответе).
polygenelubricants

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 в регулярных выражениях обозначают класс символов . Если диапазоны не указаны, он неявно или объединяет все символы в нем. Таким образом, [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было бы точнее.
polygenelubricants

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 05
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.