python MULTILINE re.findall在一个空行上进行拆分



如果输入在要分隔的字符串部分之间有2行空行,那么我有一个正则表达式会成功。但如果只有一行空白,它就会失败。你能给我建议吗?

我正在扫描一个大文件夹中的文件来查找类定义。下面是一个按预期工作的示例,它注意到2个类并将它们分离。

classstr = """class friendly():
def __init__(x, y, z):
self.x = x
self.y = y
self.z = z
def printme(): 
print(self.x)

class unfriendly():
def friendme():
assert self.x == self.y
"""
y = re.findall(r'^(classs.*)((?:n^s.+)+)', classstr, re.MULTILINE)

输出是一个包含两个元组的列表,每个元组对应一个类。

In [15]: y
Out[15]: 
[('class friendly():',
'n    def __init__(x, y, z):n        self.x = xn        self.y = yn        self.z = z'),
('class unfriendly():',
'n    def friendme():n        assert self.x == self.y')]

如果输入classstr被更改为类之间只有一个空行(示例代码中经常出现这种情况(,那么整个代码块将返回到一个blob元组中:

[('class friendly():',
'n    def __init__(x, y, z):n        self.x = xn        self.y = yn        self.z = znn    def printme():n        print(self.x)nnclass unfriendly():n    def friendme():n        assert self.x == self.y')]

显然,我不明白如何在一行空白处终止re。

建议?

有几点需要注意:

  • 使用s也可以匹配换行符
  • 在您的模式中,您使用n^s.+,这意味着下一行应该至少包含2个字符,或者一个换行符和一行至少包含一个字符

如果中间有一个空行,它将与下一部分匹配,因为ns将与换行符匹配,.+将与该行的其余部分匹配。

当有2个空行时,它将不起作用,因为n将与第一个空行匹配,s将与第二个换行符匹配,但.+无法匹配,因为该行为空。

您可以做的是匹配所有不以class开头的行,并使整行的量词*也匹配其间的空行。

^(class[^Sn].*)((?:n(?!class ).*)+)
  • ^字符串开始
  • (捕获组1
    • class[^Sn].*匹配类,后跟一个不带换行符的空白字符和该行的其余部分
  • )关闭组1
  • (捕获组2
    • (?:非捕获组(整体重复(
      • n(?!class ).*匹配换行符并断言该行不是以class开头
    • )+关闭非捕获组并重复至少1次以上
  • )关闭组2

Regex演示

我在应用已接受的答案时发现了一些小麻烦。这个解决方案确实解决了我提出的问题,但在实践中,我筛选的文件除了类之外还包括其他代码。因此,如果一个类后面有一个def,则给定的代码将在前一个类的输出中包含函数定义(因为re实际上是在寻找以"class"以外的任何字符开头的行,以确定包含(。

例如,这里的def amorous中吞噬的re

classstr = """class friendly():
def __init__(x, y, z):
self.x = x
self.y = y
self.z = z
def printme():
print(self.x)

class unfriendly():
def friendme():
assert self.x == self.y
def amorous():
x = 3
"""

为了避免这种情况,我调整了解决方案中的re,以包括所有不以字符开头的新行,而不是包括所有不从字面上以"开头的行;类";。

y = re.findall(r'^(class[^Sn].*)((?:n(?!S+).*)+)', classstr,
re.MULTILINE)
y2 = ["".join(i) for i in y]

输出是好的,至少在这个例子中是这样。

>>> pprint(y2, compact=True)
['class friendly():n'
'    def __init__(x, y, '
'z):n'
'        self.x = xn'
'        self.y = yn'
'        self.z = zn'
'n'
'    def printme():n'
'        print(self.x)n'
'n',
'class unfriendly():n'
'    def friendme():n'
'        assert self.x == self.yn']

我在等着看这次修订会造成什么其他不良影响:(

同时,我也从这一变化中发现了一些其他好处。使用类似的re来分离def函数声明可以很好地工作,即使对于嵌套函数也是如此。

最新更新