如何在Python中重复正则表达式的特定部分?

如何在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

我正在用Python进行一项信息检索任务,我试图从PDF文件中提取发票号,我已将其转换为字符串(保留原始格式),一些PDF文件在表格格式中有多个发票号。以下是一张PDF发票的示例:

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))