正则表达式以获取度量

use*_*556 5 python regex units-of-measurement

我在文件中有这些尺寸

5.3 x 2.5 cm
11 x 11 mm
7 mm 
13 x 12 x 14 mm
13x12cm
Run Code Online (Sandbox Code Playgroud)

我需要使用正则表达式使用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)
Run Code Online (Sandbox Code Playgroud)

它给出的输出:

[('13', '13', '13', '13', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''), ('12', '12', '12', '12', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''), ('4', '4', '4', '4', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''), ('25', '25', '25', '25', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''),
Run Code Online (Sandbox Code Playgroud)

Cod*_*key 6

使用正则表达式,你应该总是慢慢地建立你的表达来得到你想要的。例如

s = "5.3 x 2.5 cm"
Run Code Online (Sandbox Code Playgroud)

你想在这里找到数字吗?

re.findall("\d+", s)
Run Code Online (Sandbox Code Playgroud)

给你所有的整数:

["5", "3", "2", "5"]
Run Code Online (Sandbox Code Playgroud)

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

re.findall("\d+(?:\.\d*)?", s)
Run Code Online (Sandbox Code Playgroud)

这给了你

["5.3", "2.5"]
Run Code Online (Sandbox Code Playgroud)

然后你可以用任意数量的空格进行乘法:

re.findall("(\d+(?:\.\d*)?)\s*x\s*(\d+(?:\.\d*)?)", s)
Run Code Online (Sandbox Code Playgroud)

现在将数字放在匹配组中会为您提供一个元组。

[("5.3", "2.5")]
Run Code Online (Sandbox Code Playgroud)

然后你可以继续使用这些单位:

re.findall("(\d+(?:\.\d*)?)\s*x\s*(\d+(?:\.\d*)?)\s*(cm|mm)", s)
Run Code Online (Sandbox Code Playgroud)

给你你想要的元组:

[("5.3", "2.5", "cm")]
Run Code Online (Sandbox Code Playgroud)

等等。

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

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


Wik*_*żew 5

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

  • 您需要摆脱捕获组,因为.findall将提取捕获的所有子字符串而不是整个匹配值(但是,这并不重要,您不妨使用re.finditer并 get 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) 
Run Code Online (Sandbox Code Playgroud)

查看Python 演示打印

['5.3 x 2.5', '11 x 11', '13 x 12 x 14', '13x12cm']
Run Code Online (Sandbox Code Playgroud)

为了进一步增强它,想到的一切可能性xbycm并可能使用str.format,而不是串联。