#c# #.net #regex
#c# #.net #регулярное выражение
Вопрос:
Мне трудно понять, почему следующее выражение \[B. \]
и код возвращают количество совпадений, равное 1:
string r = "\[B. \]";
return Regex.Matches(Markup, sRegEx);
Я хочу найти все экземпляры (назовем их «тегами») (в разметке HTML-строки переменной длины, которая не содержит разрывов строк), которые имеют префикс B и заключены в квадратные скобки.
Если разметка содержит [BName]
, я получаю одно совпадение — хорошее.
Если разметка содержит [BName] [BAddress]
, я получаю одно совпадение — почему?
Если разметка содержит [BName][BAddress]
, я также получаю только одно совпадение.
В некоторых веб-тестерах регулярных выражений я заметил, что если текст содержит символ CR, я получу совпадение в строке — но мне нужен какой-то способ указать, что я хочу, чтобы совпадения возвращались независимо от разрывов строк.
Я также покопался в группах и захватил коллекции MatchCollection, но безрезультатно — всегда только один результат.
Ответ №1:
Вы получаете только одно совпадение, потому что по умолчанию регулярные выражения .NET «жадные»; они пытаются сопоставить как можно больше с помощью одного совпадения.
Поэтому, если ваше значение равно [BName][BAddress]
, у вас будет одно совпадение — которое будет соответствовать всей строке; таким образом, оно будет совпадать с [B
начала вплоть до последнего ]
— вместо первого. Если вам нужны два совпадения, используйте вместо этого этот шаблон: \[B. ?\]
?
После
указывает поисковому механизму, чтобы он соответствовал как можно меньше… оставляя вторую группу для ее собственного совпадения.
Slaks также отметил отличный вариант; конкретно указав, что вы не хотите сопоставлять окончание ]
как часть содержимого, вот так: \[B[^\]] \]
Это делает ваше совпадение «жадным», что может быть полезно в каком-то другом случае. В этом конкретном случае может быть не так много различий, но это важно иметь в виду в зависимости от того, с какими данными / шаблонами вы можете иметь дело конкретно.
Кстати, я рекомендую использовать спецификатор C # «literal string» @
для шаблонов регулярных выражений, чтобы вам не нужно было дважды экранировать что-либо в шаблонах регулярных выражений; Поэтому я бы установил шаблон следующим образом:
string pattern = @"[B. ?]";
Это значительно упрощает вычисление более сложных регулярных выражений
Комментарии:
1. Потрясающе — быстрое, хорошо написанное и даже включающее несколько дополнительных советов! Большое спасибо.
Ответ №2:
Попробуйте вместо этого использовать строку регулярного выражения \[B. ?\]
. .
само по себе (то же самое в значительной степени верно для .*
) будет соответствовать максимально возможному количеству символов, тогда как . ?
(или .*?
) будет соответствовать минимальному количеству символов, все еще удовлетворяя остальной части выражения.
Комментарии:
1. 1 за то, что также упомянул, что
?
модификатор квантора также может быть использован против*
при использовании в качестве квантора. Хотите верьте, хотите нет, но это также можно использовать против?
. Просто обратите внимание, что с помощью*
и?
он попытается сопоставить 0 раз, если это возможно. Иногда это может привести к кажущимся странными результатам.
Ответ №3:
.
это жадное совпадение; оно будет соответствовать как можно большему количеству.
Во втором примере оно совпадает BName] [BAddress
.
Вы должны написать [B[^]] ]
.
[^]]
совпадает со всеми символами, кроме ]
, поэтому он вынужден останавливаться перед первым ]
.
Комментарии:
1. 1 ; это вполне может быть лучшим вариантом, чем тот, который я изначально опубликовал, в зависимости от рассматриваемых данных. Возможно, в этом случае это не имеет значения, но, вероятно, лучше в общем случае сопоставления чего-то, что выглядит как ‘tag’. Я добавил это (с атрибуцией) к своему ответу.