如何使用 RegEx 提取模式之间的文本列表?

Posted

技术标签:

【中文标题】如何使用 RegEx 提取模式之间的文本列表?【英文标题】:How to extract the list of text between the pattern using RegEx? 【发布时间】:2022-01-13 03:16:04 【问题描述】:

我有这样的文字:

05/06/21 05/06/21 Margin Div/Int - Income ACTIVISION BLIZZARD INC

COM
Payable: 05/06/2021
QUALIFIED DIVIDENDS 23.50 

ATVI - 0.00 23.50 (9,425.77)

05/13/21 05/13/21 Margin Div/Int - Income APPLE INC
COM
Payable: 05/13/2021
QUALIFIED DIVIDENDS 6.16 

AAPL - 0.00 6.16 (9,419.61)

05/28/21 05/28/21 Margin Div/Int - Income STARBUCKS CORP
COM
Payable: 05/28/2021
QUALIFIED DIVIDENDS 18.00 

SBUX - 0.00 18.00 (9,401.61)

05/28/21 05/28/21 Margin Div/Int - Expense MARGIN INTEREST CHARGE
Payable: 05/28/2021 

 - - 0.00 (73.03) (9,474.64)

我想提取单个记录,例如:

05/06/21 05/06/21 Margin Div/Int - Income ACTIVISION BLIZZARD INC

COM
Payable: 05/06/2021
QUALIFIED DIVIDENDS 23.50 

ATVI - 0.00 23.50 (9,425.77)

05/13/21 05/13/21 Margin Div/Int - Income APPLE INC
COM
Payable: 05/13/2021
QUALIFIED DIVIDENDS 6.16 

AAPL - 0.00 6.16 (9,419.61)

05/28/21 05/28/21 Margin Div/Int - Expense MARGIN INTEREST CHARGE
Payable: 05/28/2021 

 - - 0.00 (73.03) (9,474.64)

这里每条记录的模式应该以 date(\d+/\d+/\d) 开头并以 (\n\n\d+/\d+/\d) 结尾

我试过(re.findall(r'\d+/\d+/\d(.*?)\n\n\d+/\d+/\d+',a))。但它并没有按预期工作

【问题讨论】:

您提到了“以(\n\n\d+/\d+/\d) 结尾”,但您的预期输出以\n\n 结尾。哪个是正确的? 请在代码块中显示源文本,并将换行符作为实际的换行符,而不是\n,因为这更容易在视觉上解析(我们不是计算机!)。同样,请提供一个您希望作为单个项目提取的输入片段的示例。 更新了@Inigo...! @SreeKumar,有可能在中间有日期,这就是为什么我提到它应该以 '\n\n\d+/\d+/\d' 结尾 @codingIsInteresting 谢谢。我更进一步。这对人们来说更容易阅读/理解/查看/解析/使用:) 【参考方案1】:

您可以在字符串的开头匹配类似日期的模式,并重复所有不以匹配类似日期的模式开头的行。

^\d+/\d+/\d+ .*(?:\n(?!^\d+/\d+/\d+ ).*)*

模式匹配:

^ 字符串开始 \d+/\d+/\d+ 匹配日期样模式和空格 .* 匹配该行的其余部分 (?:非捕获组 \n(?!^\d+/\d+/\d+ ).* 如果换行符不是以类似模式的日期开头,则匹配换行符和其余行 )*关闭非捕获组并选择性地重复它

查看regex demo 和Python demo。

使用可以使用 re.findall 获取所有匹配项:

import re

pattern = r"^\d+/\d+/\d+ .*(?:\n(?!^\d+/\d+/\d+ ).*)*"
 
s = ("05/06/21 05/06/21 Margin Div/Int - Income ACTIVISION BLIZZARD INC\n\n....")
 
print(re.findall(pattern, s, re.M))

【讨论】:

【参考方案2】:

你可以匹配

.+?(?=\s*(?:\d2\/\d2\/\d2 )2|$)

设置了 'g' ("global") 和 's' ("single line" 或 "dot-all") 标志。 's' 使句点匹配所有字符,包括行终止符。

Demo

正则表达式可以分解如下。

.+?                        # match one or more chars, lazily
(?=                        # begin a positive lookahead
  \s*                      # match zero or more whitespaces
  (?:                      # begin a non-capture group 
    \d2\/\d2\/\d2[ ] # match a date string followed by a space
  )2                     # end the non-capture group and execute it twice
|                          # or
  $                        # match the end of the string
)                          # end positive lookahead

【讨论】:

【参考方案3】:

您可以将此作为基础并进行更改以获得您需要的确切内容:

\d+\/\d+\/\d+(.*?)\\n\\n(\s+\d+\/\d+\/\d+|$)

你可以在demo试试。

我所做的更改如下:

\n 变为 \\n\n\n 和示例文本中的日期之间有一个空格。我在正则表达式中添加了它。 正则表达式中日期的年份部分缺失+。我已经添加了 示例中的最后一部分末尾不包含日期。该支票已包含在内。

【讨论】:

我没有得到最后一个值,也没有提取完成的数据,它跳过了日期 我还需要最后一部分@Sree Kumar @codingIsInteresting 我为此对模式进行了编辑。猜你没注意到。 我也检查过。抱歉,这不起作用 请检查输出格式。每个列表应以 2 个日期开头,并应以 \n\n 结尾。需要对正则表达式进行细微更改@Sree Kumar

以上是关于如何使用 RegEx 提取模式之间的文本列表?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 RegEx 提取单词之间的文本?

如何使用 .NET C# regex 或其他任何方法提取 *>...* 之间的文本字符串?

模式 ( regex ) 和找到的值之间的相似性

python regex提取字符之间的字符串[重复]

如何使用 regex.match 在 c# 中提取字符串的特定部分? [复制]

构建正则表达式(RegEx)以提取 HTML 标记的文本 [重复]