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

93

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

ДЕАКТИВАЦИЯ PRESCRIPTION.NET
источник
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, а не то, что вы хотите, из-за того, что классы символов (вещи в []) соответствуют символам, а не строкам.

fbstj
источник
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