【问题标题】:How to extract the list of text between the pattern using RegEx?如何使用 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 谢谢。我更进一步。这对人们来说更容易阅读/理解/查看/解析/使用:)

标签: python python-3.x regex text-extraction


【解决方案1】:

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

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

模式匹配:

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

查看regex demoPython 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*(?:\d{2}\/\d{2}\/\d{2} ){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 
        \d{2}\/\d{2}\/\d{2}[ ] # 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
      猜你喜欢
      • 1970-01-01
      • 2019-02-06
      • 2022-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      • 1970-01-01
      相关资源
      最近更新 更多