正则表达式匹配两个字符串之间的所有文本

2024-06-16 08:36:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我当前正在分析具有以下结构的日志文件:

1)时间戳,前接#字符,后接\n

2)任意#在该时间戳之后发生的事件,所有事件都后跟\n

3)重复。。在

这是一个exmaple:

#100
04!
03!
02!
#1299
0L
0K
0J
0E
#1335
06!
0X#
0[#
b1010 Z$
b1x [$
...

请原谅这些看似神秘的值,它们是代表某些“事件”的编码。在

注意:事件编码也可以使用#字符。

我要做的是数数在某个时间发生的事件的数量。在

换句话说,在时间100时,发生了3起事件。在

我试图匹配两个时间戳之间的所有文本,并通过简单地计算匹配文本中包含的新行数来计算事件数。在

我使用Python的regex引擎,并使用以下表达式:

pattern = re.compile('(#[0-9]{2,}.*)(?!#[0-9]+)')

注意:{2,}是因为我需要至少两位数字的时间戳。在

我匹配一个时间戳,继续匹配任何其他字符,直到找到另一个时间戳-结束匹配。在

它返回的结果是:

^{pr2}$

所以,我得到了时间戳-但没有事件数据-我真正关心的!在

我想这是因为消极的背后看是“贪婪的”——但我不完全确定。在

可能有一个完全不同的正则表达式,使这更简单-开放的任何建议!在

非常感谢任何帮助!在

-千


Tags: 文件引擎文本编码数量时间事件代表
3条回答

我认为regex不是一个很好的工具。你可以用一个循环。。在

>>> import collections
>>> d = collections.defaultdict(list)
>>> with open('/tmp/spam.txt') as f:
...   t = 'initial'
...   for line in f:
...     if line.startswith('#'):
...       t = line.strip()
...     else:
...       d[t].append(line.strip())
... 
>>> for k,v in d.iteritems():
...   print k, len(v)
... 
#1299 4
#100 3
#1335 6

原因是点与换行符不匹配,所以表达式只匹配包含时间戳的行;匹配不会跨越多行。您可以将"dotall" flag传递给re.compile,这样表达式将跨多行匹配。既然您说“event encodings”也可能包含一个#字符,那么您可能还需要使用多行标志,并在开始处使用^来定位匹配项,这样它只匹配行开头的#。在

如果您坚持使用基于regex的解决方案,我建议:

>>> pat = re.compile(r'(^#[0-9]{2,})\s*\n((?:[^#].*\n)*)', re.MULTILINE)
>>> for t, e in pat.findall(s):
...     print t, e.count('\n')
...
#100 3
#1299 4
#1335 6

说明:

^{pr2}$

你似乎误解了消极展望的作用。在.*之后,regex引擎首先尝试使用尽可能多的字符,然后才检查lookahead模式。如果lookahead不匹配,它将逐个字符回溯,直到匹配为止。在

但是,您可以将lookahead与非贪心的.*?一起使用。在这里,.*?将使用字符,直到lookahead在一行的开头看到一个#,或者在整个字符串的末尾:

re.compile(r'(^#[0-9]{2,})\s*\n(.*?)(?=^#|\Z)', re.DOTALL | re.MULTILINE)

相关问题 更多 >