正则表达式提取可选组

3

我有一些格式为:

T01: 警告: 标签1: 消息

T23: 标签2: 消息2

的日志字符串,我试图从中提取T号码,并检测是否存在警告:,然后在一个正则表达式中获取标签和消息的文本。但是"警告:"这个可选要求让我困惑了。

    private const string RegexExpression = @"^T(?<Number>\d+): (?<Warning>Warning:)? (?<Tag>[^:]+): (?<Message>.*)";
    private const string Message = "blar blar blar: some messsage";

    //this test works
    [TestMethod]
    public void RegExMatchByTwoNamedGroupsWarningTest()
    {
        var rex = new Regex(RegexExpression);
        const string wholePacket = "T12: Warning: logtag: " + Message;
        var match = rex.Match(wholePacket);
        Assert.IsTrue(match.Groups["Warning"].Success); //warning is present
        Assert.IsTrue(match.Success);
        Assert.IsTrue(match.Groups["Number"].Success);
        Assert.AreEqual("12", match.Groups["Number"].Value);
        Assert.IsTrue(match.Groups["Tag"].Success);
        Assert.AreEqual("logtag", match.Groups["Tag"].Value);
        Assert.IsTrue(match.Groups["Message"].Success);
        Assert.AreEqual(Message, match.Groups["Message"].Value);
    }

    [TestMethod]
    public void RegExMatchByTwoNamedGroupsNoWarningTest()
    {
        var rex = new Regex(RegexExpression);
        const string wholePacket = "T12: logtag: " + Message;
        var match = rex.Match(wholePacket);
        Assert.IsFalse(match.Groups["Warning"].Success); //warning is missing
        Assert.IsTrue(match.Success); //fails
        Assert.IsTrue(match.Groups["Number"].Success); //fails
        Assert.AreEqual("12", match.Groups["Number"].Value);
        Assert.IsTrue(match.Groups["Tag"].Success); //fails
        Assert.AreEqual("logtag", match.Groups["Tag"].Value);
        Assert.IsTrue(match.Groups["Message"].Success); //fails
        Assert.AreEqual(Message, match.Groups["Message"].Value);
    }
4个回答

1
尝试设置 RegexOptions.IgnorePatternWhitespace:
var rex = new Regex(RegexExpression, RegexOptions.IgnorePatternWhitespace);

或者,更新正则表达式模式:

private const string RegexExpression = @"^T(?<Number>\d+):\s*(?<Warning>Warning:)?\s*(?<Tag>[^:]+):\s*(?<Message>.*)";

1
@"^T(?<Number>\d+): ((?<Warning>Warning:.*) )?(?<Tag>[^:]+): (?<Message>.*)$";

我不确定关于行尾(美元)符号,因为我不熟悉c#,但是...


"$" 在 C# 中也表示行尾。 - Kash
@Kash 我也这么认为,但我不能确定,因为 Weston 自己在他的 RegExp 规则中没有使用。 - inhan

1

你的问题在于正则表达式中的空格。

如果警告组不存在,则它会尝试匹配可选警告模式之前和之后的空格。显然,你只想匹配其中一个。

解决方案是将其中一个空格与可选模式中的警告一起放置。

^T(?<Number>\d+): (?<Warning>Warning: )?(?<Tag>[^:]+): (?<Message>.*)

1

这个正则表达式考虑了空格并尽可能匹配!

@"^T(?'Number'\d+)\s*:\s*((?'Warning'\bWarning\b)\s*:)?\s*(?'Tag'.*?Tag.*?):\s*(?'Message'.*?)$"

请使用此正则表达式:RegexOptions.IgnoreCase

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接