C#regexp匹配的子表达式返回空字符串

时间:2017-01-13 22:19:01

标签: c# regex string pattern-matching

我写了这个正则表达式:

var cellPattern = new Regex(@"(?(?=\d+)\d+|\|)\s(.)\s", RegexOptions.Compiled | RegexOptions.Multiline);

从这个字符串中获取单元格:

string field = 
"  A   B   C   D   E \n" +
"1   | X |   |   |   \n" +
" ---+---+---+---+---\n" +
"2   |   |   |   |   \n" +
" ---+---+---+---+---\n" +
"3   | O |   |   |   \n" +
" ---+---+---+---+---\n" +
"4   |   |   | X |   \n" +
" ---+---+---+---+---\n" +
"5   |   |   |   |   \n" +
"O >>> ";

我正在执行cellPattern.Matches(field);它返回MatchCollection有25个匹配,但是为什么所有匹配都有一个空字符串作为第一组?

P.S .: 如果我使用命名匹配的子表达式,一切都按我想要的方式工作:所有匹配的网格单元格为“单元格”组

var cellPattern = new Regex(@"(?(?=\d+)\d+|\|)\s(?<cell>.)\s", RegexOptions.Compiled | RegexOptions.Multiline);

P.P.S:我的项目框架是.NET Framework 4.5.2

P.P.P.S:在this site上,您还可以看到此行为

1 个答案:

答案 0 :(得分:1)

这是.NET框架中的一个错误。然后使用(?(?= ) ),它会忽略下一组的内容,但它仍然会计入组的数量。

当它看到(?(时会设置一个标志来忽略下一个组,期望看到(?(expression) ... | ... ),而是有一个(?= ... ),所以该标志直到下一个才会重置捕获组。

修复方法是命名该组,添加一个虚拟组:

(?(?=\d+)\d+|\|)()\s(.)\s

或添加其他级别的parens:

(?((?=\d+))\d+|\|)\s(.)\s

在这种情况下,您还可以删除条件:

(?:\d+|\|)()\s(.)\s