如何在Python中重复正则表达式的特定部分?
我正在用Python进行一项信息检索任务,我试图从PDF文件中提取发票号,我已将其转换为字符串(保留原始格式),一些PDF文件在表格格式中有多个发票号。以下是一张PDF发票的示例:如何在Python中重复正则表达式的特定部分?,python,regex,Python,Regex,我正在用Python进行一项信息检索任务,我试图从PDF文件中提取发票号,我已将其转换为字符串(保留原始格式),一些PDF文件在表格格式中有多个发票号。以下是一张PDF发票的示例: Invoice Number Date Ac.No. Type Amount 1654339087 28.01.2019 1508765556 Invoice 1,268.40 1655214567 18.12.2018 35087535
Invoice Number Date Ac.No. Type Amount
1654339087 28.01.2019 1508765556 Invoice 1,268.40
1655214567 18.12.2018 3508753550 Invoice 3,134.20
1609833445 12.02.2019 2500444556 Invoice 2,735.84
为了从这些表中提取发票号,我创建了一个正则表达式,它帮助我从这些表中提取发票号,为了从多行中获取发票号,我重复了正则表达式的最后一部分,例如在上面的场景中,我将重复正则表达式的最后一部分(+\n(\d{5,})
)3次,这很好,但问题是我不知道PDF文件中有多少这样的行,例如10,20。在这种情况下,我需要重复regex的这一部分,重复的行数等于行数,我正在寻找一种有效的解决方案,其中我可以在regex中提到一个数字(等于总行数),或者将regex与一些要重复的数字相乘
例如:(+\n(\d{5,})*10
)或(+\n(\d{5,}){10}
)。我发现很少有类似的答案(不完全相同)提到使用{}
传递数字,但这在我的情况下不起作用。下面是我创建的正则表达式:
pattern = re.compile(r'Invoice Number\s*[A-Za-z0-9-._:\s]+\n(\d{5,}).+\n(\d{5,}).+\n(\d{5,})',re.IGNORECASE | re.MULTILINE)
预期的输出是(我目前通过重复regex的一部分3次得到):
感谢您的帮助 您可以尝试逐行读取文件,从第二行开始:
f = open('your_file.txt')
line = f.readline() # consume the header
while line:
line = f.readline()
print(re.search(r'^\d+', line).group()) # print the invoice number
f.close()
您可以尝试逐行读取文件,从第二行开始:
f = open('your_file.txt')
line = f.readline() # consume the header
while line:
line = f.readline()
print(re.search(r'^\d+', line).group()) # print the invoice number
f.close()
正如@Wiktor Stribiżew在另一个SO帖子上所建议的那样 以下解决方案适用于我使用regex的情况:
正如@Wiktor Stribiżew在另一个SO帖子上所建议的那样 以下解决方案适用于我使用regex的情况:
如果您非常需要它,请使用PyPi regex模块,请参阅。否则,将需要的部分作为一个整体捕获,然后仅对提取的块应用另一个更简单的正则表达式搜索。考虑到10行约束,匹配行之间是否会有间隙?假设3行匹配,接下来5行-不匹配,然后7行-匹配?@RomanPerekhrest-不,不会有间隙,表格将有一个标题(发票编号),然后有多行,每行都有一个发票编号。因此,我认为如果标题后的第一行在匹配中返回,那么其余的行也将匹配。很好,您可以将其作为答案发布,顺便说一句。@Wiktor Stribiżew-感谢您的评论,虽然您提供的链接中提到的问题略有不同,但它帮助我研究python regex模块,然而,对我有用的是你的答案:。使用这个解决方案,我现在已经创建了一个新的工作正则表达式,虽然它不是我想要的方式,但比我以前的解决方案要好得多,正则表达式是:
pattern=r'(?:^(?=.*Invoice Number)|\G(?!^)).\s*[a-Za-z0-9-。\uz:\s]+\n(\d{5,})
如果您非常需要它,请使用PyPi正则表达式模块,请参阅。否则,将需要的部分作为一个整体捕获,然后仅对提取的块应用另一个更简单的正则表达式搜索。考虑到10行约束,匹配行之间是否会有间隙?假设3行匹配,接下来5行-不匹配,然后7行-匹配?@RomanPerekhrest-不,不会有间隙,表格将有一个标题(发票编号),然后有多行,每行都有一个发票编号。因此,我认为如果标题后的第一行在匹配中返回,那么其余的行也将匹配。很好,您可以将其作为答案发布,顺便说一句。@Wiktor Stribiżew-感谢您的评论,虽然您提供的链接中提到的问题略有不同,但它帮助我研究python regex模块,然而,对我有用的是你的答案:。使用这个解决方案,我现在已经创建了一个新的工作正则表达式,虽然它不是我想要的方式,但比我以前的解决方案要好得多,正则表达式是:pattern=r'(?:^(?=.*Invoice Number)|\G(?!^)).\s*[a-Za-z0-9-。\uz:\s]+\n(\d{5,})
问题不是在一行的开头匹配数字,但是如何在重复组中捕获字符串的一部分。请还原复制状态。@WiktorStribiżew我不同意您的评论。根据我的经验,单个PDF(例如由Jasper reports之类的东西生成)只有一个标题。因此,OP关于重复正则表达式的问题是指对发票行应用相同的模式,而不是重复匹配整个页眉+行模式。@Tim Biegeleisen感谢您的帮助,但在尝试此操作时,只读取页眉而不读取下面的行。@manojk我对此感到惊讶,另外,while循环应该迭代文件中的每一行。也许您正在使用的脚本还有其他问题。@Tim Biegeleisen-是的,先生,很有可能,到目前为止,我使用regex软件包制定了一个有效的解决方案。问题不是在行首匹配数字,而是如何在重复组中捕获字符串的一部分。请还原复制状态。@WiktorStribiżew我不同意您的评论。根据我的经验,单个PDF(例如由Jasper reports之类的东西生成)只有一个标题。因此,OP关于重复正则表达式的问题是指对发票行应用相同的模式,而不是重复匹配整个页眉+行模式。@Tim Biegeleisen感谢您的帮助,但在尝试此操作时,只读取页眉而不读取下面的行。@manojk我对此感到惊讶,另外,while循环应该迭代文件中的每一行。也许你正在使用的脚本还有其他问题。@Tim Biegeleisen-是的,先生,很有可能,到目前为止,我使用正则表达式包制定了一个有效的解决方案。
import regex
pattern = r'(?:^(?=.*Invoice Number)|\G(?!^)).*?\s*[A-Za-z0-9-._:\s]+\n(\d{5,})'##Capture digit only having length more than 5
print(regex.findall(pattern,text,regex.M))