0

我想用一个正则表达式行(如果可能的话)将某个模式与几个字符串匹配:

blah blah (1023 mega lbs) blah blah 1245 tons
blah 1023 kilo tons blah blah 1034 metric tons
blah 1023 feet 345 blah
$100 is a lot of money

我想匹配数字(例如,第一次出现在该行中)1023 及其可能在另一个单词之后跟随它的单位(磅、吨和英尺)并将其存储为另一个字符串。但是,我必须小心 100 美元,因为它不是我关心的计量单位,也不是任何可能遵循该行第一个序列的数字。

我目前的方法有很多嵌套if statements,例如我拥有的第一行(不工作):\d*\s(.*)\s\w+有没有更好的方法来做到这一点?

4

2 回答 2

3
import re
with open("input") as f:
    for line in f:
        mo=re.match(r'[^\d]*(\d+).*?(tons|feet|lbs)', line)
        if mo: print mo.group(1), mo.group(2)

输出

1023 lbs
1023 tons
1023 feet

此外,如果您有类似 的行$100 money is too much for 100 lbs,则可以使用:

import re
with open("input") as f:
    for line in f:
        mo=re.match(r'.*?(?<![$\d])(\d+).*?(tons|feet|lbs)', line)
        if mo: print mo.group(1), mo.group(2)

并匹配公斤,巨型的东西:

import re
with open("input") as f:
    for line in f:
        mo=re.match(r'.*?(\d+).*?(mega|kilo|metric|) (tons|feet|lbs)', line)
        if mo: print mo.group(1), mo.group(2), mo.group(3)

输出

1023 mega lbs
1023 kilo tons
1023  feet
100  lbs

可以将这些单位和修饰符存储在列表中,并将它们加入其中|以动态创建正则表达式。

匹配所有可能的单位修饰符的示例:

import re
with open("input") as f:
    for line in f:
        mo=re.match(r'[^\d]*(\d+).*?(\S*)\s*(tons|feet|lbs)', line)
        if mo: print "'{}' '{}' '{}'".format(mo.group(1), mo.group(2), 
                       mo.group(3))

输出

'1023' 'mega' 'lbs'
'1023' 'kilo' 'tons'
'1023' '' 'feet'
于 2013-05-28T22:12:28.897 回答
0

您可能喜欢使用正则表达式测试器,例如http://regexpal.com/http://rubular.com/

你有一个问题,因为(.*)中间会贪婪地匹配并最终捕获比你预期的更多。见这里

请注意,我的解决方案应该匹配所有实例,<number> <scale> <unit>而不仅仅是每行第一次出现。我把它留在这里留给后代。

(?:[^0-9$]|^)(\d+)\s(\w+)\s(\w+)

这是在行动,链接

(?:[^0-9$]|^)表示匹配要么从行首开始,要么前面有不是数字或美元符号的东西(?:意味着我们不想捕获它)。然后匹配数字\d+后跟两个单词\w+。您可以将\w+s 替换为 perreal 的答案中更具描述性的匹配项。

于 2013-05-28T22:47:58.873 回答