Как я могу расставить приоритеты перекрывающихся шаблонов в RegEx?
Я видел несколько похожих вопросов, даже один, который я написал сам, но это довольно специфично.
В регулярных выражениях есть образец совпадения. Теперь скажите, что в одной и той же строке есть два шаблона соответствия, которые могут соответствовать тексту. Кажется, моя удача всегда опирается на регулярное выражение, соответствующее неправильному шаблону. (Я использую.Net Regex в C#)
У меня есть два типа строк, которые мне нужно разбить:
01 - Первое значение |02 - Второе значение | Пробел - Игнорировать
А также:
A - Первое значение BlankB - Второе значение C - Третье значение
Поэтому мой желаемый результат - сопоставить код со значением одной строкой шаблона.
Code,Meaning
01,First Value
02,Second Value
Blank,Ignore
A,First Value
blank,
B,Second Value
C,Third Value
Я пробовал несколько шаблонов, но никогда не могу понять, что это правильно. Самое близкое, что я смог получить:
(([A-Z0-9]{1,4})[ \-–]{1,3}|([Bb]lank)[ \-–]{0,3})(([A-Z][a-z]+[.,;| ]?)+)
Мой срыв:
[A-Z0-9]{1,4}[ \-–]{1,3}
-> соответствует коду, верхнему регистру или количеству символов длиной от 1 до 4, за которыми следуют от 1 до 3 символов пробела, дефиса или mdash из html.
или же
[Bb]lank[ \-–]{0,3}
-> пробел после 0-3 символов пробела, дефиса или mdash из html
затем
(([A-Z][a-z]+[.,;| ]?)+)
-> должно соответствовать любому множеству слов, включая возможный пробел. поэтому первое и значение, второе и значение должны совпадать.
Первоначальная проблема заключается в том, что последняя группа шаблонов соответствует значению "Valueblank" во второй входной строке. Я хочу как-то расставить приоритеты, чтобы "[Bb]lank" соответствовал как часть первой группы, так и НИКОГДА не часть второй группы.
Я пытался положить (?![Bb]lank)
Негативный взгляд в финальной группе, но, похоже, это никогда не сработает. Любая помощь будет оценена.
Спасибо
Jaeden "Sifo Dyas" al'Raec Ruiner
2 ответа
Как насчет следующего ( пример regex101.com):
/((?:[A-Z0-9]{1,4}|[Bb]lank)(?=\h[-–]\h)|[Bb]lank)(?:\h[-–]\h|\|)?(.*?)(?=[Bb]lank|\||[A-Z0-9]{1,4}\h[-–]\h|$)/gm
объяснение
[Bb]lank
Все совпадения для "пустой" проверки для строчной ИЛИ заглавной буквы "В"
((?:[A-Z0-9]{1,4}|[Bb]lank)(?=\h[-–]\h)|[Bb]lank)
1-я группа захвата: сопоставьте либо первое буквенно-цифровое значение, либо первое "пустое" значение с " - " или " - " после (положительный взгляд) ИЛИ "пустое" первое значение, которое не будет иметь 2-ю подходящую группу.
(?:\h[-–]\h|\|)?
Разделитель " - " ИЛИ " - " ИЛИ "|" что произойдет ноль или один раз.
(.*?)
Несправедливо сопоставлять 2-ю подходящую группу.
(?=[Bb]lank|\||[A-Z0-9]{1,4}\h[-–]\h|$)
Используя позитивный взгляд, ищите "пустой" ИЛИ "|" ИЛИ буквенно-цифровое первое значение с " - " или " - " после ИЛИ конца строки (чтобы поймать последний элемент в строке), чтобы найти конец, где мы должны захватить
Regex выберет первое самое длинное совпадение, то есть если два шаблона начнут совпадать в одной и той же позиции и совпадут с одинаковым количеством символов, будет выбрана более ранняя альтернатива.
например, следующий (глупый пример) всегда будет соответствовать первой альтернативе по предпочтению второй: (.+)|foo
В вашем случае, если вы действительно хотите сопоставить два элемента, где один начинается с цифры, а другой с буквы, почему бы не сделать: ([0-9]+...)|([A-Za-z]....)
Соответствуйте двум альтернативам как можно раньше.