Вопрос или проблема
Я хочу разобрать следующий текст, используя регулярные выражения, с правилами, указывающими некоторые правила отклонения
AB CD => Принять
ABCD => Принять
ABCDEF => Принять (любое четное число подходит)
AB ?? CD EF => Принять
AB ? CD EF => Принять как особый случай
AB?CDEF => Отклонить (потому что знак вопроса может сделать его неоднозначным)
AB??CDEF => Принять (ясно, что последовательный шаблон четный)
ABCD ? ?DEF => Отклонить
ABCD ?? DDEF => Принять
Нет необходимости в группе захвата, просто сопоставьте первое
Мое текущее регулярное выражение ((\?|([0-9a-fA-F?]{2})+)\s*)*
Ответ или решение
Для решения задачи по созданию регулярного выражения (регекса) для разбора строк, основанных на шестнадцатеричном представлении с учётом вопросительного знака, необходимо учитывать заданные правила принятия и отклонения строк. Давайте подробно разберем, как можно формировать необходимое регулярное выражение и что учитываются в каждом случае.
Анализ требований
Давайте сначала разграничим строки, соответствующие критериям "Приемлемо" и "Отклоняемо":
-
Приемлемо:
AB CD
— нормальная строка.ABCD
— нормально, т.к. каждая пара из двух символов.ABCDEF
— нормально, пара (6 символов).AB ?? CD EF
— допустимо, т.к.??
указывает на четное количество символов.AB ? CD EF
— специальный случай, допустимо.AB??CDEF
— однозначно, (не вызывает неоднозначности).ABCD ?? DDEF
— четное количество (пробелов не требуется).
-
Отклоняемо:
AB?CDEF
— тут возникает неоднозначность.ABCD ? ?DEF
— две отдельные пробелы не допустимы.
Построение регулярного выражения
Теперь сформируем регулярное выражение. Необходимо учесть все случаи:
- Символы от
0-9
иA-F
могут составлять группы по два символа. - Вопросительный знак (
?
) может появляться в условиях, что четное число символов подразумевает, что он может следовать за четным количеством других символов. - Пробелы (
\s*
) могут располагаться между символами или группами.
Регулярное выражение
Основываясь на вышеизложенном, оптимальное регулярное выражение будет выглядеть следующим образом:
^(?:(?:[0-9A-F]{2}|\?[0-9A-F]{2})\s*)*(?:\?\?\s*(?:[0-9A-F]{2}|\?[0-9A-F]{2})|\?[0-9A-F]{2}|\?[0-9A-F]|\s*)*$|(?:(?<=^|\s)(?:[0-9A-F]{2}|\?[0-9A-F]{2})(?=\s|$))*
Объяснение компонентов regex:
(?:[0-9A-F]{2}|\?[0-9A-F]{2})
— соответствует двум шестнадцатеричным символам или двум символам с вопросительным знаком перед ними.- *`\s`** — используется для обозначения возможных пробелов между группами.
- *`(?:\?\?\s(?:[0-9A-F]{2}|\?[0-9A-F]{2})|\?[0-9A-F]{2}|\?[0-9A-F]|\s)`** — отвечает за случаи с вопросительными знаками, где они могут следовать за четным количеством других символов и пробелов.
- *`(?:(?<=^|\s)(?:[0-9A-F]{2}|\?[0-9A-F]{2})(?=\s|$))`** — проверяет начало и конец строки на наличие соответствия.
Заключение
Разработка этого регулярного выражения с учётом всех бизнес-требований позволяет эффективно парсить строки, используя заданные правила легитимности. Это даст вам возможность не только корректно разделять и идентифицировать потоки данных, но и обеспечит минимизацию ошибок и неоднозначности. Таким образом, предложенное регулярное выражение удовлетворяет всем условиям задачи, обеспечивая надежный и понятный способ для разбора данных.