Сопоставить текст с несколькими регулярными выражениями в 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))