如何使用正则表达式匹配从 A 到 B 的任何内容,其中 B 前面没有 C

How to use regex to match anything from A to B, where B is not preceeded by C

我很难接受这个。首先,这是我要匹配的字符串的困难部分:

"a \"b\" c"

我想从中提取的内容如下:

a \"b\" c

当然,这只是一个较大字符串的子字符串,但其他一切都按预期工作。问题是使正则表达式忽略用反斜杠转义的引号。

我研究过各种方法,但没有任何方法能得到正确的结果。我最近的尝试是这样的:

"((\"|[^"])+?)"

在各种在线测试中,它按应有的方式工作 - 但是当我构建我的 ASP.NET 页面时,它在第一个 " 处中断,只留下 a 字母,白色 space 和一个反斜杠。

上述模式背后的逻辑是捕获所有 \" 或不是 " 的实例。我希望这会搜索 \",确保首先找到那些 - 但我觉得这被表达式的第二部分覆盖了,它只有 1 个字符。单个反斜杠不匹配 2 个字符( \"),但它会作为非“”进行匹配,从那里开始,下一个字符将是一个“”,匹配完成。 (这只是我关于为什么我的模式失败的假设。)

关于这个有什么建议吗?我在正则表达式中尝试了 "look"-methods 的各种组合,但我并没有真正取得任何进展。我也觉得这就是我需要的。

原始答案

要匹配像 a \"b\" c 这样的字符串,您需要使用以下正则表达式声明:

(?:\"|[^"])+
var rx = Regex(@"(?:\""|[^""])+");

参见 RegexStorm demo

这是一个 IDEONE demo:

var str = "a \\"b\\" c";
Console.WriteLine(str);
var rx = new Regex(@"(?:\""|[^""])+");
Console.WriteLine(rx.Match(str).Value);

请注意字符串文字前面的 @ 让我们可以使用 verbatim 字符串文字,我们必须用双引号来匹配文字引号并使用单转义斜线而不是双斜线。这使得正则表达式更易于阅读和维护。

如果您想匹配输入字符串中的任何转义实体,您可以使用:

var rx = new Regex(@"[^""\]*(?:\.[^""\]*)*");

See demo on RegexStorm

更新

要匹配带引号的字符串,只需在模式周围添加引号:

var rx = new Regex(@"""(?<res>[^""\]*(?:\.[^""\]*)*)""");

此模式比 Tim Long 建议的正则表达式产生更好的性能,请参阅 RegexHero 测试结果:

以下表达式对我有用:

"(?<Result>(\"|.)*)"

表达式匹配如下:

  • 开场白(字面意思 "
  • 一个命名的捕获 (?<name>pattern) 包括:
    • 零次或多次出现 * 文字 \" 或 (|) 任何单个字符 (.)
  • 最终收盘价(文字 "

请注意,*(零个或多个)量词是非贪婪的,因此最终引号与文字 " 而不是 "any single character" . 匹配部分。

我使用 ReSharper 9 内置的正则表达式验证器开发表达式并验证结果:

我使用了 "Explicit Capture" 选项来减少输出中的杂物 (RegexOptions.ExplicitCapture)。

需要注意的一件事是我匹配整个字符串,但我只是捕获子字符串,使用命名捕获。使用命名捕获是获得所需结果的一种非常有用的方法。在代码中,它可能看起来像这样:

    static string MatchQuotedString(string input)
        {
        const string pattern = @"""(?<Result>(\""|.)*)""";
        const RegexOptions options = RegexOptions.ExplicitCapture;
        Regex regex = new Regex(pattern, options);
        var matches = regex.Match(input);
        var substring = matches.Groups["Result"].Value;
        return substring;
        }

优化:如果您计划大量使用正则表达式,您可以将其分解到一个字段中并使用 RegexOptions.Compiled 选项,这会预编译表达式并以牺牲速度提高吞吐量更长的初始化时间。