正则表达式提取可选组

我有一些格式的日志字符串:

T01: Warning: Tag1: Message

T23: Tag2: Message2

我试图提取T号,检测Warning:的存在Warning: ,然后在一个正则表达式中标记和消息的文本。 “警告:”的可选要求让我感到沮丧。

  private const string RegexExpression = @"^T(?\d+): (?Warning:)? (?[^:]+): (?.*)"; 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); } 

你的问题是你的正则表达式中的空白。

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

解决方案是在可选模式中包含一个空格以及警告。 即:

 ^T(?\d+): (?Warning: )?(?[^:]+): (?.*) 

尝试设置RegexOptions.IgnorePatternWhitespace

 var rex = new Regex(RegexExpression, RegexOptions.IgnorePatternWhitespace); 

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

 private const string RegexExpression = @"^T(?\d+):\s*(?Warning:)?\s*(?[^:]+):\s*(?.*)"; 
 @"^T(?\d+): ((?Warning:.*) )?(?[^:]+): (?.*)$"; 

我不确定行尾(Dollar)的标志,因为我不熟悉c#,但……

这个正则表达式考虑空间并尽力而为!

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

将此Regex与RegexOptions.IgnoreCase一起RegexOptions.IgnoreCase