如果输入在要分隔的字符串部分之间有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个字符,或者一个换行符和一行至少包含一个字符
如果中间有一个空行,它将与下一部分匹配,因为n
和s
将与换行符匹配,.+
将与该行的其余部分匹配。
当有2个空行时,它将不起作用,因为n
将与第一个空行匹配,s
将与第二个换行符匹配,但.+
无法匹配,因为该行为空。
您可以做的是匹配所有不以class
开头的行,并使整行的量词*
也匹配其间的空行。
^(class[^Sn].*)((?:n(?!class ).*)+)
^
字符串开始(
捕获组1class[^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
函数声明可以很好地工作,即使对于嵌套函数也是如此。