您需要解析一个 SonicWall syslog 文件,该文件具有以下格式:
<134>id=firewall sn=C0EAE470F7D0 time="2014-08-13 04:31:27" fw=10.2.3.4 pri=6 c=1024 m=537 msg="Connection Closed" n=301541 src=172.16.1.43:50581:X0 dst=172.16.1.1:192:X0 proto=udp/192 sent=46
您希望创建一个正则表达式,该表达式将返回一个列表,其中包含按等号拆分的元组。如果值包含空格,则会使用双引号。您希望返回的值中不包含引号,同时希望包含空格的整个值。例如,您希望时间键包含日期和时间。
您希望获得以下输出:
("<134>id","firewall"), ("sn","C0EAE470F7D0"), ("time", '"2014-08-13 04:31:27"')
("fw","1.2.3.4"), ("pri","6"), ... ("msg", '"Connection Closed"'), ("n", "301541")
("src","172.16.1.43:50581:X0"), ... ("sent", "46")
您尝试了以下正则表达式,但当遇到带有双引号的字段时,它会失败。此外,最后一个字段“sent”也不会被返回。
import re
fname = "syslog.log"
with open(fname) as fp: lines = fp.read().splitlines()
q = re.compile('(.*?)=(.*?)[\s"]',re.S|re.M)
for line in lines:
print(line)
key_val = q.findall(line)
print(key_val)
该代码返回以下内容:
[('<134>id', 'firewall'), ('sn', 'C0EAE470F7D0'), ('time', ''), ('2014-08-13 04:31:27" fw', '10.2.3.4'), ('pri', '6'),('c', '1024'), ('m', '537'), ('msg', ''), ('Connection Closed" n', '301541'), ('src', '172.16.1.43:50581:X0'), ('dst', '172.16.1.1:192:X0'), ('proto', 'udp/192')]
如果您无法使用正则表达式来完成此任务,那么在 Python 3.3 中实现所需结果的最佳方法是什么?
2、解决方案 您可以使用以下正则表达式来解析日志文件:
(.+?)=("[^"]*"|\S*)\s*
该正则表达式将匹配以下内容:
- 任何数量的非等号字符,直到遇到等号
- 一个双引号,其后跟任意数量的非双引号字符,再跟一个双引号
- 或者,任何数量的非空格字符
该正则表达式将捕获两个组:
- 第一个组是键
- 第二个组是值
您可以使用以下代码来使用该正则表达式解析日志文件:
import re
with open("syslog.log") as f:
for line in f:
key_val = re.findall(r'''(.+?)=("[^"]*"|\S*)\s*''', line)
print(key_val)
该代码将打印以下内容:
[('<134>id', 'firewall'), ('sn', 'C0EAE470F7D0'), ('time', '"2014-08-13 04:31:27"'), ('fw', '10.2.3.4'), ('pri', '6'), ('c', '1024'), ('m', '537'), ('msg', '"Connection Closed"'), ('n', '301541'), ('src', '172.16.1.43:50581:X0'), ('dst', '172.16.1.1:192:X0'), ('proto', 'udp/192'), ('sent', '46')]
如果您希望删除值中的引号,则可以使用以下正则表达式:
(.+?)=(?:"(.*?)(?<!\)"|(\S*))\s*
该正则表达式将捕获三个组:
- 第一个组是键
- 第二个组是值,不包含引号
- 第三个组是值,包含引号
您可以使用以下代码来使用该正则表达式解析日志文件:
import re
with open("syslog.log") as f:
for line in f:
key_val = re.findall(r'''(.+?)=(?:"(.*?)(?<!\)"|(\S*))\s*''', line)
print(key_val)
该代码将打印以下内容:
[('<134>id', 'firewall'), ('sn', 'C0EAE470F7D0'), ('time', '2014-08-13 04:31:27'), ('fw', '10.2.3.4'), ('pri', '6'), ('c', '1024'), ('m', '537'), ('msg', 'Connection Closed'), ('n', '301541'), ('src', '172.16.1.43:50581:X0'), ('dst', '172.16.1.1:192:X0'), ('proto', 'udp/192'), ('sent', '46')]