SysLog RFC5424 的正则表达式

Posted

技术标签:

【中文标题】SysLog RFC5424 的正则表达式【英文标题】:Regular Expression for SysLog RFC5424 【发布时间】:2018-03-01 11:47:21 【问题描述】:

我正在编写一个 SysLog 服务器,我的程序在其中接收 RFC5424Format 的消息。

我的程序必须解析消息并存储值。

我有一个无法解析消息的正则表达式。

正则表达式有问题。我是正则表达式的新手。

任何帮助表示赞赏。

public static void Main()
    
        string RFC5424Format = @"(\<(?<PRI>\d+)\>(?<VERSION>\d+)?)? \ * (?<TIMESTAMP> ( (?<YEAR>\d+) - (?<MONTH>\d+) - (?<DAY>\d+) ) T+ (?<HOUR>\d+): (?<MINUTE>\d+): (?<SECOND>\d+) (\.(?<MILLISECONDS>\d+))? (?<OFFSET>Z|(\+|\-)\d+:\d+)? ) \ (?<HOSTNAME>[\w!-~]+) \ (?<APPNAME>[\w!-~]+) \ (?<PROCID>[\w!-~]+) \ (?<MSGID>[\w!-~]+) \  (?<SD>-|(\[.*\])) \ ?(?<MESSAGE>.*)?";

        Regex rfc5424 = new Regex("^" + RFC5424Format + "$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace);

        string input = "< 38 > 1 2018 - 03 - 01T16: 05:51.799465 + 05:30 AAEINBLR07229L Source_UDP - -\n ??? MessageContent_Via_UDP - 5424";

        Match m = rfc5424.Match(input);

        if (m.Success)
        
            Console.WriteLine("Regex is fine");
        
        else
        
            Console.WriteLine("Problem in Regex");
        
    

【问题讨论】:

请提供一些例子,什么是对的,什么是错的。仅给出了一个示例(我想这应该匹配),我们没有其他东西可以检查我们的答案或正确回答 【参考方案1】:

我最近才遇到这个问题。根据RFC 5424,Syslog 消息应采用以下格式:HEADER SP STRUCTURED-DATA [SP MSG],其中 SP 是空格字符,括号表示数据是可选的。话虽如此,当我实例化 Regex 对象进行比较时,我发现将消息分解为三个单独的正则表达式模式然后将它们组合起来更容易。

这是我的示例课程。希望对你有帮助。

public class SyslogMessage

    private static readonly string _SyslogMsgHeaderPattern = @"\<(?<PRIVAL>\d1,3)\>(?<VERSION>[1-9]0,2) (?<TIMESTAMP>(\S|\w)+) (?<HOSTNAME>-|(\S|\w)1,255) (?<APPNAME>-|(\S|\w)1,48) (?<PROCID>-|(\S|\w)1,128) (?<MSGID>-|(\S|\w)1,32)";
    private static readonly string _SyslogMsgStructuredDataPattern = @"(?<STRUCTUREDDATA>-|\[[^\[\=\x22\]\x20]1,32( ([^\[\=\x22\]\x20]1,32=\x22.+\x22))?\])";
    private static readonly string _SyslogMsgMessagePattern = @"( (?<MESSAGE>.+))?";
    private static Regex _Expression = new Regex($@"^_SyslogMsgHeaderPattern _SyslogMsgStructuredDataPattern_SyslogMsgMessagePattern$", RegexOptions.None, new TimeSpan(0, 0, 5));
    
    public int Prival  get; private set; 
    public int Version  get; private set; 
    public DateTime TimeStamp  get; private set; 
    public string HostName  get; private set; 
    public string AppName  get; private set; 
    public string ProcId  get; private set; 
    public string MessageId  get; private set; 
    public string StructuredData  get; private set; 
    public string Message  get; private set; 
    public string RawMessage  get; private set; 

    /// <summary>
    /// Parses a Syslog message in RFC 5424 format. 
    /// </summary>
    /// <exception cref="FormatException"></exception>
    /// <exception cref="OverflowException"></exception>
    /// <exception cref="ArgumentNullException"></exception>
    /// <exception cref="InvalidOperationException"></exception>
    public static SyslogMessage Parse(string rawMessage)
    
        if (string.IsNullOrWhiteSpace(rawMessage))  throw new ArgumentNullException("message"); 

        var match = _Expression.Match(rawMessage);
        if (match.Success)
        
            return new SyslogMessage
            
                Prival = Convert.ToInt32(match.Groups["PRIVAL"].Value),
                Version = Convert.ToInt32(match.Groups["VERSION"].Value),
                TimeStamp = Convert.ToDateTime(match.Groups["TIMESTAMP"].Value),
                HostName = match.Groups["HOSTNAME"].Value,
                AppName = match.Groups["APPNAME"].Value,
                ProcId = match.Groups["PROCID"].Value,
                MessageId = match.Groups["MSGID"].Value,
                StructuredData = match.Groups["STRUCTUREDDATA"].Value,
                Message = match.Groups["MESSAGE"].Value,
                RawMessage = rawMessage
            ;
        
        else  throw new InvalidOperationException("Invalid message."); 
    

    public override string ToString()
    
        var message = new StringBuilder($@"<Prival:###>Version:## TimeStamp.ToString("yyyy-MM-ddTHH:mm:ss.fffK") HostName AppName ProcId MessageId StructuredData");

        if (!string.IsNullOrWhiteSpace(Message))
        
            message.Append($" Message");
        

        return message.ToString();
    

【讨论】:

【参考方案2】:

正则表达式总是需要大量的思考和测试才能正确。我没有时间解决所有问题,但我可以告诉你,你几乎走在了正确的轨道上。我已经重写并测试了 Regex 的一部分(没有锚定),并将其包含在此处以供参考:

\< *(?<PRI>\d+) *\> *(?<VERSION>\d+)? *(?<YEAR>\d+) - (?<MONTH>\d+) - (?<DAY>\d+)T(?<HOUR>\d+): *(?<MINUTE>\d+):(?<SECOND>\d+)\.(?<MILLISECONDS>\d+) *\+ *(?<OFFSET>\d+:\d+) *(?<HOSTNAME>\b\w+\b) *(?<SOURCE>\b\w+\b)

我一直发现https://www.regexpal.com/ 有助于调试正则表达式问题。慢慢来,一步一步的接近。告诉我结果如何!

【讨论】:

以上是关于SysLog RFC5424 的正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

解析 Syslog 中的正则表达式帮助

log4j2 和 syslog,使用 RFC5424 格式不显示日志消息的可变参数部分

syslog的Python正则表达式解析

根据 RFC5321/RFC5322 对电子邮件地址进行正则表达式验证

正则表达式根据 RFC2822 验证消息 ID

是否有正则表达式来验证 Base32 :: RFC 3548