【问题标题】:regex to get measurements正则表达式获取测量值
【发布时间】:2018-02-11 04:22:36
【问题描述】:

我在文档中有这些测量值

5.3 x 2.5 cm
11 x 11 mm
7 mm 
13 x 12 x 14 mm
13x12cm

我需要使用 python 使用正则表达式提取 5.3 x 2.5 厘米。

到目前为止,我的代码如下,但它不能正常工作

x = "\.\d{1,2}|\d{1,4}\.?\d{0,2}|\d{5}\.?\d?|\d{6}\.?"
by = "( )?(by|x)( )?"
cm = "(mm|cm|millimeter|centimeter|millimeters|centimeters)"
x_cm = "((" + x + " *(to|\-) *" + cm + ")" + "|(" + x + cm + "))"
xy_cm = "((" + x + cm + by + x + cm + ")" +"|(" + x + by + x + cm + ")" +"|(" + x + by + x + "))"
xyz_cm = "((" + x + cm + by + x + cm + by + x + cm + ")" + "|(" + x + by + x + by + x + cm + ")" + "|(" + x + by + x + by + x + "))"
m = "((" + xyz_cm + ")" + "|(" + xy_cm + ")" + "|(" + x_cm + "))"
a = re.compile(m)
print a.findall(text)

它给出的输出:

[('13', '13', '13', '13', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''), ('12', '12', '12', '12', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''), ('4', '4', '4', '4', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''), ('25', '25', '25', '25', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''),

【问题讨论】:

  • 定义“不能正常工作”:它做什么与它应该做什么?示例将是最受欢迎的。
  • 请展示并解释你得到的输出和你想要的输出之间的区别。
  • 您必须做的一件事是摆脱捕获组。但是,您应该在连接后检查final pattern,它只有returns numbers only
  • 检查对您的“非捕获组”目标的帮助(?:blabla),这可能有助于纳入 Wiktors 评论。
  • 非常感谢@WiktorStribiżew,它的速度如此之快,解决了我的大部分问题。最终我的目标是提取文本中的所有测量值,因此我也需要提取它们的单位。我的计划是将所有内容提取为“5.3 x 2.5 cm”之类的字符串。 1)有意义吗? 2)我该怎么做,有什么建议吗?

标签: python regex units-of-measurement


【解决方案1】:

使用 Regex,您应该始终缓慢地构建您的表达式以获得您想要的。例如

s = "5.3 x 2.5 cm"

你想在这里找到数字吗?

re.findall("\d+", s)

给你所有的整数:

["5", "3", "2", "5"]

好的,如果您的数字可以是浮点数,但不一定非要如此,那该怎么办。然后你用一个非捕获匹配组扩展你的表达式,该匹配组有一个点,后面可能还有一些数字。

re.findall("\d+(?:\.\d*)?", s)

这给了你

["5.3", "2.5"]

然后你可以乘以任意数量的空格:

re.findall("(\d+(?:\.\d*)?)\s*x\s*(\d+(?:\.\d*)?)", s)

现在将数字放入匹配组中会给您一个元组。

[("5.3", "2.5")]

然后您可以继续使用单位:

re.findall("(\d+(?:\.\d*)?)\s*x\s*(\d+(?:\.\d*)?)\s*(cm|mm)", s)

给你你想要的元组:

[("5.3", "2.5", "cm")]

等等。

如果你像这样构建你的正则表达式,你就有机会看到从一个更改到下一个更改的中断。像您在上面发布的那样调试一个巨大的正则表达式是一项不值得去做的任务。

我不会将我的单元正则表达式命名为cm,这对于将来维护您的代码的任何人来说都是相当混乱的。除此之外,您需要对要允许的数字格式有一些明确的要求。也许有人会输入科学记数法等。你的正则表达式会变得非常复杂。

【讨论】:

  • 谢谢它解决了我的问题!也非常感谢您的详细解释!!!
  • 只有一个尺寸(7 毫米)时它唯一找不到的东西,但我会弄清楚的。
  • @user1979556 我认为这可以作为练习留给读者;-)。
  • 但是,我还是做不到 :)
【解决方案2】:

当前正则表达式的唯一问题是两个:

  • 您需要摆脱捕获组,因为.findall 将提取所有捕获的子字符串而不是整个匹配值(但是,这并不重要,您不妨使用re.finditer 并获取match.group(0)
  • 主要问题是您没有对x 模式进行分组,数字格式交替破坏了最终模式的结构。

快速修复看起来像

x = "(?:\.\d{1,2}|\d{1,4}\.?\d{0,2}|\d{5}\.?\d?|\d{6}\.?)"
by = "(?: )?(?:by|x)(?: )?"
cm = "(?:mm|cm|millimeter|centimeter|millimeters|centimeters)"
x_cm = "(?:" + x + " *(?:to|\-) *" + cm + "|" + x + cm + ")"
xy_cm = "(?:" + x + cm + by + x + cm +"|" + x + by + x + cm +"|" + x + cm + by + x +"|" + x + by + x + ")"
xyz_cm = "(?:" + x + cm + by + x + cm + by + x + cm + "|" + x + by + x + by + x + cm + "|" + x + by + x + by + x + ")"
m = "{}|{}|{}".format(xyz_cm, xy_cm, x_cm) 

查看Python demo打印

['5.3 x 2.5', '11 x 11', '13 x 12 x 14', '13x12cm']

要进一步增强它,请考虑xbycm 的所有可能性,并可能使用str.format 而不是串联。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多