如何使用 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 提取模式之间的文本列表?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 .NET C# regex 或其他任何方法提取 *>...* 之间的文本字符串?