【问题标题】:Odd Regex behaviour in C#C# 中的奇怪正则表达式行为
【发布时间】:2015-10-07 12:23:39
【问题描述】:

我做了以下正则表达式:

(?<=^PR)(?:[gpr])?([A-Z]{2,3})(?:vB)?(?=\d{4}$)

适用于任何正则表达式测试器。但是,当我在 C# 中尝试它时,它的行为有点奇怪。假设我将这 3 个字符串与它进行比较:

PRPCP2008, PRrSV2012 and PRBP2006

正则表达式测试器匹配以下内容:

PCP, SV and BP

这就是我想要发生的事情。我只关心“PR”和任何 4 位数年份之间的 2 或 3 个大写字母。我确实寻找小写字符,但不想匹配它们。现在,当我在 C# 中使用相同的正则表达式时,我得到不同的匹配:

PCP, rSV and BP

PCP 和 BP 仍然相同。但现在它还包括小写的“r”。在 c# 中发生这种情况是否有原因?还是我只是偶然发现了一个有问题的正则表达式测试器?

如果您想测试正则表达式,我使用了以下正则表达式测试器:http://derekslager.com/blog/posts/2007/09/a-better-dotnet-regular-expression-tester.ashx

编辑: 好的,代码

string regexPattern = @"(?<=^PR)(?:[gpr])?([A-Z]{2,3})(?:vB)?(?=\d{4}$)";

Regex regex = new Regex(regexPattern , RegexOptions.None);
Match match = regex.Match("PRrSV2012");

Console.WriteLine(match.Value);

【问题讨论】:

  • 我在 C# 中尝试过 - 怎么样?请张贴代码。您是否使用逐字字符串文字来声明正则表达式?
  • 我在您引用的网站中尝试了您的模式和字符串。返回 0 个匹配项。最好能用英文说出你想要的规则,让我们帮助你
  • 请注意,不同的正则表达式引擎会以不同的方式执行某些正则表达式。确保在测试时使用一个专门具有 C# 或 .Net 选项的工具。
  • 我的错。我的意思是 PRCP2008 等作为单个字符串。不是一次全部。
  • 得到这个match.Groups[1] 而不是match.Value

标签: c# regex


【解决方案1】:

您正在查看匹配值,但您需要一个组。

var rx = new Regex(@"(?<=^PR)(?:[gpr])?(?'interest'[A-Z]{2,3})(?:vB)?(?=\d{4}$)", RegexOptions.None);

var items = new[] { "PRPCP2008", "PRrSV2012", "PRBP2006", "Foo"};

var results = items.Select(i => new { i, isMatch = rx.IsMatch(i), value = rx.Matches(i).Cast<Match>().Select(m => m.Groups["interest"].Value).FirstOrDefault()});

结果:

PRPCP2008 True PCP 
PRrSV2012 True SV 
PRBP2006 True BP 
Foo False null 

这就是我总是在我的表达式中使用明确命名的组的原因。

【讨论】:

    【解决方案2】:

    据我所知,您需要使用 1 个正则表达式匹配多个子字符串。然后,您需要取消锚定模式(即删除 ^$):

    (?<=PR)(?:[gpr])?([A-Z]{2,3})(?:vB)?(?=\d{4})
    

    在 C# 中:

    var reg = new Regex(@"(?<=PR)(?:[gpr])?([A-Z]{2,3})(?:vB)?(?=\d{4})");
    var matches = reg.Matches(str).Cast<Match>().Select(p => p.Value).ToList();
    

    然后,您将获得 3 场比赛。

    regex demo

    更新

    您只需要使用.Groups[1].Value 访问PRrSV2012 中的SV,请参见demo

    string regexPattern = @"(?<=^PR)(?:[gpr])?([A-Z]{2,3})(?:vB)?(?=\d{4}$)";
    Regex regex = new Regex(regexPattern , RegexOptions.None);
    Match match = regex.Match("PRrSV2012");
    Console.WriteLine(match.Groups[1].Value);
    //                      ^^^^^^^^^
    

    IDEONE demo

    MSDN 中没有直接说明 Regex.Match 对象包含捕获组,但这是隐含的,因为 Match.Value 包含整个匹配的文本。捕获组是其中的一部分,因此应在找到匹配项后访问。

    【讨论】:

    • 为什么需要不区分大小写?
    猜你喜欢
    • 2012-03-02
    • 2018-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-17
    • 2013-07-13
    • 1970-01-01
    相关资源
    最近更新 更多