【问题标题】:How do I match an entire line from a text file and break it into variable using Python and RegEx?如何匹配文本文件中的整行并使用 Python 和 RegEx 将其分解为变量?
【发布时间】:2017-04-28 11:52:19
【问题描述】:

您好,我在使用 RegEx 和 Python 时遇到以下问题。

我正在尝试从文本文件中获取以下内容并将其分解为变量(文本文件包含 28k+ 行,而不仅仅是以下文本):

VOLUME 26 4—PART 23

该行中仅有的两个常量值是 VOLUME 和 PART,数字交替出现。

理想情况下,上述字符串将从文本文件中匹配并解析为 3 个变量。

volume = 26
epitome = 4
part = 23

我试过了:

^.*VOLUME.*$

不幸的是,上面的 RegEx 在找到单词卷后匹配了整个文件。我只需要一行。

提前致谢!

【问题讨论】:

  • 试试d = {k:int(v) for k,v in zip(['volume','epitome','part'],re.findall('\d+',txt))}

标签: python regex


【解决方案1】:

您可以使用\d 正则表达式模式匹配数字,使用\D 模式匹配非数字字符。您还需要在要捕获的组周围加上括号,以便 matchfindall 将返回这些组。

import re
s = "VOLUME 26 4—PART 23"
pattern = re.compile('VOLUME (\d+) (\d+)—PART (\d+)')
print(pattern.findall(s))

如果您不确定 VOLUME 和 PART 是否始终相同,您可以改用这个更通用的模式:

pattern = re.compile('\D+(\d+) (\d+)\D+(\d+)')

运行任一模式打印:

[('26', '4', '23')]

要将结果提取到您的变量中,请将print() 行替换为:

result = pattern.findall(s)[0]
volume, epitome, part = (int(i) for i in result)

与可选的缩影匹配

您可以通过将中间项目(缩影)包装在非捕获组(?:...) 中来使其成为可选。在此之后使用? 告诉它匹配 0 或 1 次出现,它适用于有或没有缩影的行。如果缺少缩影,result 元组中的第二个元素将是一个空字符串''

下面是工作示例:

import re
sl = ["VOLUME 26 4—PART 23", "VOLUME 16 4-PART 7", "VOLUME 12-PART 38"]
pattern = re.compile('\D+(\d+)(?: (\d+))?\D+(\d+)')
for s in sl:
    result = pattern.findall(s)[0]
    volume, epitome, part = (int(i) if i else i for i in result)
    print('"{}": v {}, e {}, p {}'.format(s, volume, epitome, part))

运行它会产生:

"VOLUME 26 4—PART 23": v 26, e 4, p 23
"VOLUME 16 4-PART 7": v 16, e 4, p 7
"VOLUME 12-PART 38": v 12, e , p 38

【讨论】:

  • 像魅力一样工作。但是,如果音量是 3 位数,我认为这行不通?例如第 123 卷 5-PART 126
  • @CodeHard 它仍然可以工作。 \d+ 匹配一个或多个数字字符。您可以在以下位置进行测试:regex101.com/r/UtpXZi/1
  • 无论如何在中间整数上会有一点损失,因为某些文件有:第 12 卷第 38 部分,而其他文件有第 16 卷第 4 部分第 7 部分。尽管如此,你已经回答了原始问题,我非常感谢。
  • @CodeHard - 我用正则表达式更新了我的答案,该正则表达式可以处理缺少缩影的情况。我还更新了 Regex101 的代码,以便您了解它是如何工作的。
  • 我知道我不应该在 cmets 中感谢你。不过,我从你身上学到了很多。感谢您分享您的时间。
【解决方案2】:

在 python 2.7 中

import re
s = "sdfdsjflsfVOLUME 26 4—PART 23sfldfls = VOLUME 26 4—PART 23sjjkfj"
regex = r"VOLUME.\d+.\d+.[^PART]+PART.\d+"
all_patterns = re.findall(regex, s)
for pattern in all_patterns:
    volume, epitome, part = map(int, re.findall(r'\d+', pattern))
    print(volume, epitome, part)

在python3中

import re
s = "sdfdsjflsfVOLUME 26 4—PART 23sfldfls = VOLUME 26 4—PART 23sjjkfj"
regex = re.compile("VOLUME.\d+.\d+—PART.\d+")
all_patterns = regex.findall(s)
for pattern in all_patterns:
    r = re.compile("\d+")
    volume, epitome, part = map(int, r.findall(pattern))
    print(volume, epitome, part)

【讨论】:

  • 不返回任何匹配项。变量为空。
  • 还是不行。不返回任何匹配项,变量为空。
  • @CodeHard 复制上面的代码并运行它。它会起作用的。或者你能用你的代码更新问题吗?
  • 我完全使用了您的代码,进程以退出代码 0 完成是打印到终端的唯一状态。
  • Windows 10 Python 3.6.1,很抱歉,它对我不起作用。我很感激你的时间。
猜你喜欢
  • 2016-02-02
  • 1970-01-01
  • 2022-12-04
  • 2023-03-30
  • 2020-08-11
  • 2020-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多