多行正则表达式匹配检索行号和匹配

时间:2021-05-04 15:35:48

标签: python python-3.x regex

我正在尝试遍历文件中的所有行以匹配可能的模式;

  1. 出现在文件中的任何位置
  2. 在同一个文件中多次出现
  3. 在同一行出现多次
  4. 对于一个正则表达式模式,我正在搜索的字符串可能会分布在多行中

一个示例输入是;

new File()
new
File()
there is a new File()
new
    
    
    
File()
there is not a matching pattern here File() new
new File() test new File() occurs twice on this line

示例输出为;

new File() Found on line 1  
new File() Found on lines 2 & 3 
new File() Found on line 4 
new File() Found on lines 5 & 9 
new File() Found on line 11
new File() Found on line 11 
6 occurrences of new File() pattern in test.txt (Filename)

正则表达式模式看起来像;

pattern = r'new\s+File\s*\({1}\s*\){1}'

查看文档 here,我可以看到 match、findall 和 finditer 都在字符串的开头返回匹配项,但我没有看到使用搜索函数的方法来查看正则表达式的任何位置我们要搜索的字符串位于多行(我上面的要求中的第四个)。

简单到足以匹配每行超过一次的正则表达式;

示例输入:

line = "new File() new File()"

代码:

i = 0
matches = []
while i < len(line):
    while line:
        matchObj = re.search(r"new\s+File\s*\({1}\s*\){1}", line, re.MULTILINE | re.DOTALL)
        if matchObj:
            line = line[matchObj.end():]
            matches.append(matchObj.group())

print(matches)

打印以下匹配项 - 目前不包括行号等:

['new File()', 'new File()']

有没有办法用 Python 的正则表达式来做我正在寻找的东西?

2 个答案:

答案 0 :(得分:1)

您可以先找到文本中的所有 \n 字符及其各自的位置/字符索引。由于每个 \n...嗯...开始一个新行,此列表中每个值的索引指示找到的 \n 字符终止的行号。然后搜索所有出现的模式并使用上述列表查找匹配的开始/结束位置...

import re
import bisect

text = """new 
File()
aa new File()
new
File()
there is a new File() and new
File() again
new
    
    
    
File()
there is not a matching pattern here File() new
new File() test new File() occurs twice on this line
"""

# character indices of all \n characters in text
nl = [m.start() for m in re.finditer("\n", text, re.MULTILINE|re.DOTALL)]

matches = list(re.finditer(r"(new\s+File\(\))", text, re.MULTILINE|re.DOTALL))
match_count = 0
for m in matches:
    match_count += 1
    r = range(bisect.bisect(nl, m.start()-1), bisect.bisect(nl, m.end()-1)+1)
    print(re.sub(r"\s+", " ", m.group(1), re.DOTALL), "found on line(s)", *r)
print(f"{match_count} occurrences of new File() found in file....")

输出:

new File() found on line(s) 0 1
new File() found on line(s) 2
new File() found on line(s) 3 4
new File() found on line(s) 5
new File() found on line(s) 5 6
new File() found on line(s) 7 8 9 10 11
new File() found on line(s) 13
new File() found on line(s) 13
8 occurrences of new File() found in file....

答案 1 :(得分:1)

可以先统计匹配前的换行数,然后再统计匹配值中的换行数,并合并行号: 请参阅Python demo

import re
s='new File()\nnew\nFile()\nthere is a new File()\nnew\n \n \n \nFile()\nthere is not a matching pattern here File() new\nnew File() test new File() occurs twice on this line'
pattern = r'new\s+File\s*\(\s*\)'
for m in re.finditer(pattern, s):
    linenums = [s[:m.start()].count('\n') + 1]
    for _ in range(m.group().count('\n')):
        linenums.append(linenums[-1] + 1)
    print('{} Found on line {}'.format(re.sub(r'\s+', ' ', m.group()), ", ".join(map(str,linenums))))

参见online Python demo

输出:

new File() Found on line 1
new File() Found on line 2, 3
new File() Found on line 4
new File() Found on line 5, 6, 7, 8, 9
new File() Found on line 11
new File() Found on line 11
相关问题