I have some log strings in the format:
T01: Warning: Tag1: Message
T23: Tag2: Message2
I am trying to extract the T number, detect the presence of Warning:, then text of the Tag and Message all in one regex. The optional requirement of "Warning:" is tripping me up though.
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);
}
Your problem is the whitespace in your regex.
If the warning group is not there then it is trying to match the space from before the optional warning pattern and the one from after. Clearly you only want to match one of them.
The solution is to have one of the spaces inside the optional pattern along with the warning. ie:
^T(?<Number>\d+): (?<Warning>Warning: )?(?<Tag>[^:]+): (?<Message>.*)
Try to set RegexOptions.IgnorePatternWhitespace:
var rex = new Regex(RegexExpression, RegexOptions.IgnorePatternWhitespace);
Or, update regex pattern:
private const string RegexExpression = @"^T(?<Number>\d+):\s*(?<Warning>Warning:)?\s*(?<Tag>[^:]+):\s*(?<Message>.*)";
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With