2013-05-28 7 views
0

Я хотел, чтобы соответствовать определенному шаблону на несколько строк с одним регулярным выражением строкой в ​​(если это возможно):Matching Regex в Python

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+ Есть ли лучший способ сделать это?

ответ

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' 
+0

Я также хочу захватить единицы измерения между числом и фактическим устройством, например '1023 килотонн' –

+0

Ответ работает хорошо, но для меня это сложно.Если бы я не знал, что термины «средний» были бы «(мега | километр | метрикой»), я мог бы вместо этого ('*)' вместо этого? –

+0

Я пробовал его с помощью '(. *)' И он работал (однако, я получил дополнительное пространство перед средним словом. Но когда я попробовал его с '\ w +', он не работал –

0

Вы могли бы с помощью регулярных выражений, таких как тестер http://regexpal.com/ или http://rubular.com/.

У вас возникли проблемы, потому что (.*) посередине будет соответствовать жадности и в конечном итоге захватит больше, чем вы предполагали. См. here.

Обратите внимание, что мое решение должно соответствовать всем экземплярам <number> <scale> <unit> не только первому вхождению на строку. Я оставляю его здесь для потомков.

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

Это его действие, link.

(?:[^0-9$]|^) говорит, что матч начинается либо в начале строки, либо перед ним стоит что-то, что не является значком или знаком доллара (?: означает, что мы не хотим его снимать). Затем сопоставьте номер \d+, а затем два слова \w+. Вы можете заменить \w+ с более описательными совпадениями, как в ответе perreal.