Сопоставить текст с несколькими регулярными выражениями в python

У меня есть текстовый корпус из 11 файлов, каждый из которых имеет около 190000 строк. У меня есть 10 строк, одна или несколько из которых могут появляться в каждой строке вышеупомянутого корпуса.

Когда я сталкиваюсь с любой из 10 строк, мне нужно записать эту строку, которая появляется в строке отдельно. Метод грубой силы, проходящий через регулярное выражение для каждой строки и помечающий его, занимает много времени. Есть ли эффективный способ сделать это?

Я нашел пост ( Совпадение строки с несколькими регулярными выражениями с использованием Python), который обеспечивает вывод TRUE или FALSE. Но как мне записать соответствующее регулярное выражение из строки:

any(regex.match(line) for regex in [regex1, regex2, regex3])

Редактировать: добавление примера

regex = ['quick','brown','fox']
line1 = "quick brown fox jumps on the lazy dog" # i need to be able to record all of quick, brown and fox
line2 = "quick dog and brown rabbit ran together" # i should record quick and brown
line3 = "fox was quick an rabit was slow" # i should be able to record quick and fox.

Обход регулярного выражения и запись подходящего - одно из решений, но, глядя на масштаб (11 * 190000 * 10), мой сценарий работает некоторое время. Мне нужно повторять это в моей работе довольно много раз. так что я искал более эффективный способ.

2 ответа

Решение

Подход ниже в том случае, если вы хотите совпадения. В случае, если вам нужно регулярное выражение в списке, которое вызвало совпадение, вам не повезло, и вам, вероятно, потребуется цикл.

На основании ссылки, которую вы предоставили:

import re
regexes= 'quick', 'brown', 'fox'
combinedRegex = re.compile('|'.join('(?:{0})'.format(x) for x in regexes))

lines = 'The quick brown fox jumps over the lazy dog', 'Lorem ipsum dolor sit amet', 'The lazy dog jumps over the fox'

for line in lines:
    print combinedRegex.findall(line)

выходы:

['quick', 'brown', 'fox']
[]
['fox']

Дело в том, что вы не перебираете регулярные выражения, а комбинируете их. Разница с циклическим подходом заключается в том, что re.findall не найдет перекрывающихся совпадений. Например, если ваши регулярные выражения были: regexes= 'bro', 'own', вывод строк выше будет:

['bro']
[]
[]

тогда как циклический подход приведет к:

['bro', 'own']
[]
[]

Если вы просто пытаетесь сопоставить буквенные строки, возможно, это проще сделать:

strings = 'foo','bar','baz','qux'
regex = re.compile('|'.join(re.escape(x) for x in strings))

и тогда вы можете проверить все это сразу:

match = regex.match(line)

Конечно, вы можете получить строку, которая соответствует из результирующего MatchObject:

if match:
    matching_string = match.group(0)

В бою:

import re
strings = 'foo','bar','baz','qux'
regex = re.compile('|'.join(re.escape(x) for x in strings))

lines = 'foo is a word I know', 'baz is a  word I know', 'buz is unfamiliar to me'

for line in lines:
    match = regex.match(line)
    if match:
        print match.group(0)

Похоже, вы действительно ищете строку для своего регулярного выражения. В этом случае вам нужно будет использовать re.search (или какой-то вариант), а не re.match неважно, что ты делаешь. Пока ни одно из ваших регулярных выражений не пересекается, вы можете использовать моё вышеуказанное решение с re.findall:

matches = regex.findall(line)
for word in matches:
    print ("found {word} in line".format(word=word))

Другие вопросы по тегам