Python 用于解析跨越多行的 sudoers 日志内容的正则表达式

Python regex to parse contents of sudoers log that spans accross multiple lines

我需要从数百个 sudo.log 文件中提取日期、用户和执行的命令。 问题是 sudo 日志条目跨越多行并且命令可以有多行。

sudoers 中的条目示例如下:

Aug  7 14:14:43 : user1 : TTY=pts/53 ; PWD=/path2 ;
    USER=root ; COMMAND=/path/to/cmd1
Aug  7 14:14:49 : user2 : TTY=pts/53 ; PWD=/usr/home ;
    USER=root ; COMMAND=./myscript.sh -m name -o SCHEDULER
Aug  7 14:15:14 : user3 : TTY=pts/34 ;
    PWD=/path ; USER=root ;
    COMMAND=/usr/bin/egrep ^[a-z]*
    /filename/toto1234
Aug  7 14:15:37 : user4 : TTY=unknown ; PWD=/opt/nagios ; USER=root ;
    COMMAND=/path/to/less
    /var/opt/otherfile
Aug  7 14:16:04 : user4 : TTY=pts/34 ;
    PWD=/usr/local/bin/script ; USER=root ;
    COMMAND=/usr/bin/egrep ^[a-z]*
    /user/local/sbin/tata

注意到的是 sudoers 的每个条目都以日期开头。后跟一个冒号,然后是用户,然后在另一行执行命令。我想捕获日期、用户和命令..

我想我应该捕获 COMMAND 之后的所有内容,直到再次找到日期?

我有这个捕获日期和用户名的正则表达式,因为它们往往在同一行,但不知道如何捕获命令

这是我目前所拥有的:

(^\w{3}\s+\d+\s\d+:\d+:\d+)\s?:\s?(\w+?)\s+:.*

我一直在这里测试它:

https://regex101.com/r/qFnv0t/2/

我的想法可能是让命令捕获所有内容,直到 group1 再次匹配?或者首先我需要修改日志文件并每行输入一个条目?

感谢您的见解。

您可以使用捕获组并首先匹配所有不包含 COMMAND 的行。

然后从 COMMAND 之后匹配到以 "date like" 模式开头的第一行。

您不必使用问号使匹配单词字符非贪婪\w+?

^(\w{3}\s+\d+\s\d+:\d+:\d+)\s?:\s?(\w+)\s+:.*(?:\r?\n(?!.*COMMAND).*)*\r?\n.*?COMMAND=(.*(?:\r?\n(?!\w{3}\s+\d+\s\d+).*)*)

关于图案

  • ^ 字符串开头
  • ( 捕获 组 1
    • \w{3}\s+\d+\s\d+:\d+:\d+ 匹配日期格式
  • ) 关闭组 1
  • \s?:\s? 匹配被可选空白字符包围的 :
  • ( 捕获 第 2 组
    • \w+ 匹配 1+ 个单词字符
  • ) 关闭组 2
  • \s+:.* 匹配 1+ 个空白字符,: 和 0+ 次除换行符外的任何字符
  • (?: 非捕获组
  • \r?\n(?!.*COMMAND).*匹配换行符,断言该行不包含COMMAND。然后匹配 0+ 次除换行符之外的任何字符
  • )*关闭组重复0+次
  • \r?\n.*?COMMAND= 匹配换行符直到第一次出现 COMMAND=
  • ( 捕获 第 3 组
    • .* 匹配除换行符以外的任何字符 0+ 次
    • (?:非捕获组
      • \r?\n(?!\w{3}\s+\d+\s\d+).* 匹配换行符,断言该行不是以类似日期的模式开头,然后匹配该行的其余部分
    • )* 关闭非捕获组并重复 0+ 次,因为命令可以跨越多行
  • ) 关闭组 3

Regex demo | Python example

请注意,类日期格式本身不会验证日期。