我正在传递XML文档,作为文本文档,虽然是正则表达式过程。
<YaddaYaddaPrecedingMarkup>includes (a) and (b) and (c) and (d) and ...
<MyElement>SECTIONBEGINS (a) Item A (b) Item B (c) Item C (d) Item D</MyElement>
<YaddaYaddaFollowingMarkup>includes (a) and (b) and (c) and (d) and ...
我希望我的正则表达式捕获子弹标签'(a)''(b)''(c)''(d)'。 (.. etc ...)出现在'MyElement'中,其文本以“SECTIONBEGINS”开头。
我需要这个正则表达式来忽略(a)......(b)......(c)出现在我的XML-as-text中的其他任何实例。
如果我使用:
(\([a-z]\))
我在整个文件中匹配(a),(b),(c)。那个表达太不受限制了。
如果我使用:
>SECTIONBEGINS(?:.*?)(\([a-z]\))(?:.*)<
我只在正确的部分内成功匹配,但我只匹配'(a)'(第一个匹配),而不匹配同一部分的(b),(c),(d)。
我已经尝试了很多其他的变体,其中一些会选择'(d)',但似乎没有任何变种可以捕获多个。
答案 0 :(得分:2)
变式1:Lookbehind
(?<=SECTIONBEGINS[^>]*)\([a-z]\)
变式2:\ G anchor + capture group
(?:SECTIONBEGINS|\G)[^<(]*(\([a-z]\))
答案 1 :(得分:1)
您需要查看Match.Group.Captures
:
Regex.Match(xml, @">SECTIONBEGINS (?<items>\([a-z]\) .+?)+<")
.Groups["items"].Captures.Cast<Capture>()
.Select(x => x.Value)
或者,如果您想将它们分组为键/值对:
var match = Regex.Match(xml, @">SECTIONBEGINS( (\((?<index>[a-z])\) (?<item>.+?)))+<");
Enumerable.Zip(
match.Groups["index"].Captures.Cast<Capture>(),
match.Groups["item"].Captures.Cast<Capture>(),
Tuple.Create)
.ToDictionary(x => x.Item1.Value, x => x.Item2.Value)
编辑:如果您不关心子弹标签,可以通过以下方式提取项目:
Regex.Match(xml, @">SECTIONBEGINS( (\((?<index>[a-z])\) (?<item>.+?)))+<")
.Groups["item"].Captures.Cast<Capture>()
.Select(x => x.Value)
或者,如果您想要替换原有内容:
Regex.Replace(xml, @">SECTIONBEGINS( (\((?<index>[a-z])\) (?<item>.+?)))+<",
m => string.Format(">SECTIONBEGINS {0}<", string.Join(" ", m.Groups["item"]
.Captures.Cast<Capture>()
.Select((x,i) => string.Format("({0}) {1}",
(char)(((int)'a')+i),
x.Value.ToUpper() // TODO: your replace logic here
))))
)