gpt4 book ai didi

python - Python 中的多行匹配

转载 作者:太空狗 更新时间:2023-10-29 21:55:21 26 4
gpt4 key购买 nike

我已经阅读了所有我能找到的文章,甚至理解了其中的一些,但作为一个 Python 新手,我仍然有点迷茫,希望得到帮助:)

我正在编写一个脚本来从特定于应用程序的日志文件中解析感兴趣的项目,每一行都以我可以匹配的时间戳开头,我可以定义两件事来识别我想要捕获的内容,一些是部分的content 和一个字符串,它将终止我想要提取的内容。

我的问题是多行的,在大多数情况下,每个日志行都以换行符终止,但有些条目包含 SQL,其中可能有新行,因此会在日志中创建新行。

所以,在一个简单的情况下,我可能会这样:

[8/21/13 11:30:33:557 PDT] 00000488 SystemOut     O 21 Aug 2013 11:30:33:557 [WARN] [MXServerUI01] [CID-UIASYNC-17464] BMXAA6720W - USER = (ABCDEF) SPID = (2526) app (ITEM) object (ITEM) : select * from item  where ((status != 'OBSOLETE' and itemsetid = 'ITEMSET1') and (exists (select 1 from maximo.invvendor where (exists (select 1 from maximo.companies where (( contains(name,'  $AAAA  ') > 0 )) and (company=invvendor.manufacturer and orgid=invvendor.orgid))) and (itemnum = item.itemnum and itemsetid = item.itemsetid)))) and (itemtype in (select value from synonymdomain where domainid='ITEMTYPE' and maxvalue = 'ITEM')) order by itemnum asc  (execution took 2083 milliseconds)

这一切都显示为一行,我可以与之匹配:

re.compile('\[(0?[1-9]|[12][0-9]|3[01])(\/)(0?[1-9]|[12][0-9]|3[01])(\/)([0-9]{2}).*(milliseconds)')

然而,在某些情况下,SQL 中可能会有换行符,因此我仍想捕获它(并可能用空格替换换行符)。我目前正在一次一行地阅读文件,这显然行不通,所以...

  1. 我需要一次处理整个文件吗?它们的大小通常为 20mb。如何读取整个文件并遍历它以查找单行或多行 block ?
  2. 我该如何编写一个多行正则表达式来匹配一行中的所有内容或分布在多行中的内容?

我的总体目标是对其进行参数化,以便我可以使用它来提取匹配起始字符串(始终是一行的开头)、结束字符串(我想要捕获到的位置)和值的不同模式的日志条目这是它们之间的标识符。

在此先感谢您的帮助!

克里斯。

import sys, getopt, os, re

sourceFolder = 'C:/MaxLogs'
logFileName = sourceFolder + "/Test.log"
lines = []
print "--- START ----"
lineStartsWith = re.compile('\[(0?[1-9]|[12][0-9]|3[01])(\/)(0?[1-9]|[12][0-9]|3[01])(\/)([0-9]{2})(\ )')
lineContains = re.compile('.*BMXAA6720W.*')
lineEndsWith = re.compile('(?:.*milliseconds.*)')

lines = []
with open(logFileName, 'r') as f:
for line in f:
if lineStartsWith.match(line) and lineContains.match(line):
if lineEndsWith.match(line) :
print 'Full Line Found'
print line
print "- Record Separator -"
else:
print 'Partial Line Found'
print line
print "- Record Separator -"

print "--- DONE ----"

下一步,对于我的部分行,我将继续阅读,直到找到 lineEndsWith 并将这些行组合成一个 block 。

我不是专家,所以随时欢迎提出建议!

更新 - 所以我让它工作了,感谢所有帮助指导事情的回应,我意识到它并不漂亮,我需要清理我的 if/elif 困惑并使其更有效率,但它正在工作!感谢所有帮助。

import sys, getopt, os, re

sourceFolder = 'C:/MaxLogs'
logFileName = sourceFolder + "/Test.log"

print "--- START ----"

lineStartsWith = re.compile('\[(0?[1-9]|[12][0-9]|3[01])(\/)(0?[1-9]|[12][0-9]|3[01])(\/)([0-9]{2})(\ )')
lineContains = re.compile('.*BMXAA6720W.*')
lineEndsWith = re.compile('(?:.*milliseconds.*)')

lines = []

multiLine = False

with open(logFileName, 'r') as f:
for line in f:
if lineStartsWith.match(line) and lineContains.match(line) and lineEndsWith.match(line):
lines.append(line.replace("\n", " "))
elif lineStartsWith.match(line) and lineContains.match(line) and not multiLine:
#Found the start of a multi-line entry
multiLineString = line
multiLine = True
elif multiLine and not lineEndsWith.match(line):
multiLineString = multiLineString + line
elif multiLine and lineEndsWith.match(line):
multiLineString = multiLineString + line
multiLineString = multiLineString.replace("\n", " ")
lines.append(multiLineString)
multiLine = False

for line in lines:
print line

最佳答案

Do I need to process the whole file in one go? They are typically 20mb in size. How do I read the entire file and iterate through it looking for single or multi-line blocks?

这里有两个选项。

您可以逐 block 读取文件,确保将每个 block 末尾的任何“剩余”位附加到下一个 block 的开头,然后搜索每个 block 。当然,您必须通过查看您的数据格式以及您的正则表达式可以匹配的内容来弄清楚什么算作“剩余”,理论上可以将多个 block 都算作剩余……

或者你可以 mmap文件。 mmap 的作用类似于字节(或类似于 Python 2.x 中的 str),并由操作系统根据需要处理分页 block 的进出。除非您尝试处理绝对巨大的文件(32 位为千兆字节,64 位甚至更多),否则这是微不足道且高效的:

with open('bigfile', 'rb') as f:
with mmap.mmap(f.fileno(), length=0, access=mmap.ACCESS_READ) as m:
for match in compiled_re.finditer(m):
do_stuff(match)

在旧版本的 Python 中,mmap 不是上下文管理器,因此您需要将其包裹在 contextlib.closing 中(或者只使用显式 close 如果你愿意的话)。


我将如何编写一个多行正则表达式来匹配一行中的整个内容或它分布在多行中?

您可以使用 DOTALL标志,它使 . 匹配换行符。您可以改为使用 MULTILINE标记并放入适当的 $ 和/或 ^ 字符,但这会使简单的情况变得更加困难,而且很少需要这样做。这是一个 DOTALL 示例(使用更简单的正则表达式使其更明显):

>>> s1 = """[8/21/13 11:30:33:557 PDT] 00000488 SystemOut     O 21 Aug 2013 11:30:33:557 [WARN] [MXServerUI01] [CID-UIASYNC-17464] BMXAA6720W - USER = (ABCDEF) SPID = (2526) app (ITEM) object (ITEM) : select * from item  where ((status != 'OBSOLETE' and itemsetid = 'ITEMSET1') and (exists (select 1 from maximo.invvendor where (exists (select 1 from maximo.companies where (( contains(name,'  $AAAA  ') > 0 )) and (company=invvendor.manufacturer and orgid=invvendor.orgid))) and (itemnum = item.itemnum and itemsetid = item.itemsetid)))) and (itemtype in (select value from synonymdomain where domainid='ITEMTYPE' and maxvalue = 'ITEM')) order by itemnum asc  (execution took 2083 milliseconds)"""
>>> s2 = """[8/21/13 11:30:33:557 PDT] 00000488 SystemOut O 21 Aug 2013 11:30:33:557 [WARN] [MXServerUI01] [CID-UIASYNC-17464] BMXAA6720W - USER = (ABCDEF) SPID = (2526) app (ITEM) object (ITEM) : select * from item where ((status != 'OBSOLETE' and itemsetid = 'ITEMSET1') and
(exists (select 1 from maximo.invvendor where (exists (select 1 from maximo.companies where (( contains(name,' $AAAA ') > 0 )) and (company=invvendor.manufacturer and orgid=invvendor.orgid))) and (itemnum = item.itemnum and itemsetid = item.itemsetid)))) and (itemtype in (select value from synonymdomain where domainid='ITEMTYPE' and maxvalue = 'ITEM')) order by itemnum asc (execution took 2083 milliseconds)"""
>>> r = re.compile(r'\[(.*?)\].*?milliseconds\)', re.DOTALL)
>>> r.findall(s1)
['8/21/13 11:30:33:557 PDF']
>>> r.findall(s2)
['8/21/13 11:30:33:557 PDF']

如您所见,第二个 .*? 与空格一样容易匹配换行符。

如果您只是想将换行符视为空格,则两者都不需要; '\s' 已经捕获换行符。

例如:

>>> s1 = 'abc def\nghi\n'
>>> s2 = 'abc\ndef\nghi\n'
>>> r = re.compile(r'abc\s+def')
>>> r.findall(s1)
['abc def']
>>> r.findall(s2)
['abc\ndef']

关于python - Python 中的多行匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18494497/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com