[英]python MULTILINE re.findall spliting on one blank line
如果输入在我想要分隔的字符串部分之间有 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'^(class\s.*)((?:\n^\s.+)+)', classstr, re.MULTILINE)
输出是一个包含两个元组的列表,每个类一个。
In [15]: y
Out[15]:
[('class friendly():',
'\n def __init__(x, y, z):\n self.x = x\n self.y = y\n 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 = x\n self.y = y\n self.z = z\n\n def printme():\n print(self.x)\n\nclass unfriendly():\n def friendme():\n assert self.x == self.y')]
显然,我无法理解如何在单个空行上终止 re。
建议?
有几点需要注意:
\\s
也可以匹配换行符\\n^\\s.+
意味着下一行应包含至少 2 个字符,或换行符和至少包含一个字符的行如果中间有 1 个空行,它将匹配下一部分,因为\\n
和\\s
将匹配换行符,而.+
将匹配该行的其余部分。
当有 2 个空行时它不起作用,因为\\n
将匹配第一个空行,然后\\s
将匹配第二个换行符但.+
无法匹配,因为该行为空。
您可以做的是匹配所有不以class
开头的行,并使整行*
的量词也匹配中间的空行。
^(class[^\S\n].*)((?:\n(?!class ).*)+)
^
字符串开始(
捕获组 1
class[^\\S\\n].*
匹配类后跟一个没有换行符的空白字符和该行的其余部分)
关闭第 1 组(
捕获组 2
(?:
非捕获组(整体重复)
\\n(?!class ).*
匹配一个换行符并断言该行不以class
开头)+
关闭非捕获组并重复至少 1+ 次)
关闭第 2 组我在应用接受的答案时发现了一些麻烦。 该解决方案确实解决了我提出的问题,但实际上我正在筛选的文件包含除类之外的其他代码。 因此,如果类后面有一个def
,给定的代码将在前一个类的输出中包含函数定义(因为 re` 正在逐行查找以除“类”以外的任何内容开头的行以确定包含)。
例如, re
狼吞虎咽的def amorous
在这里:
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
以包含所有不以字符开头的新行,而不是包含所有不以“class”开头的行。
y = re.findall(r'^(class[^\S\n].*)((?:\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 = x\n'
' self.y = y\n'
' self.z = z\n'
'\n'
' def printme():\n'
' print(self.x)\n'
'\n',
'class unfriendly():\n'
' def friendme():\n'
' assert self.x == self.y\n']
我在等着看这个修订会导致什么其他不良影响:)
同时,我还从这一变化中发现了其他一些好处。 使用类似的re
来分隔def
函数声明效果很好,即使对于嵌套函数也是如此。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.