Захват содержимого регулярных выражений и их эффективное удаление - PullRequest
7 голосов
/ 15 октября 2008

Положение:

  • текст: строка
  • R: регулярное выражение, соответствующее части строки. Это может быть дорого рассчитать.

Я хочу удалить R-совпадения из текста и посмотреть, что они на самом деле содержат. В настоящее время я делаю это как:

import re
ab_re = re.compile("[ab]")
text="abcdedfe falijbijie bbbb laifsjelifjl"
ab_re.findall(text)
# ['a', 'b', 'a', 'b', 'b', 'b', 'b', 'b', 'a']
ab_re.sub('',text)
# 'cdedfe flijijie  lifsjelifjl'

Это запускает регулярное выражение дважды, насколько я могу судить. Есть ли способ сделать все это на проходе, возможно, используя re.split? Похоже, что с решениями, основанными на разделении, мне нужно было бы сделать регулярное выражение как минимум вдвое.

Ответы [ 4 ]

4 голосов
/ 15 октября 2008

Что по этому поводу:

import re

text = "abcdedfe falijbijie bbbb laifsjelifjl"
matches = []

ab_re = re.compile( "[ab]" )

def verboseTest( m ):
    matches.append( m.group(0) )
    return ''

textWithoutMatches = ab_re.sub( verboseTest, text )

print matches
# ['a', 'b', 'a', 'b', 'b', 'b', 'b', 'b', 'a']
print textWithoutMatches
# cdedfe flijijie  lifsjelifjl

Аргумент 'repl' функции re.sub может быть функцией, так что вы можете сообщать или сохранять совпадения оттуда, и что бы функция не возвращала, это то, что будет заменять sub.

Функция может быть легко изменена, чтобы сделать намного больше! Проверьте документацию по модулю на docs.python.org для получения дополнительной информации о том, что еще возможно.

4 голосов
/ 15 октября 2008
import re

r = re.compile("[ab]")
text = "abcdedfe falijbijie bbbb laifsjelifjl"

matches = []
replaced = []
pos = 0
for m in r.finditer(text):
    matches.append(m.group(0))
    replaced.append(text[pos:m.start()])
    pos = m.end()
replaced.append(text[pos:])

print matches
print ''.join(replaced)

Выходы:

['a', 'b', 'a', 'b', 'b', 'b', 'b', 'b', 'a']
cdedfe flijijie  lifsjelifjl
3 голосов
/ 15 октября 2008

Мой пересмотренный ответ, используя re.split () , что делает вещи за один проход регулярного выражения:

import re
text="abcdedfe falijbijie bbbb laifsjelifjl"
ab_re = re.compile("([ab])")
tokens = ab_re.split(text)
non_matches = tokens[0::2]
matches = tokens[1::2]

(редактировать: вот полная версия функции)

def split_matches(text,compiled_re):
    ''' given  a compiled re, split a text 
    into matching and nonmatching sections
    returns m, n_m, two lists
    '''
    tokens = compiled_re.split(text)
    matches = tokens[1::2]
    non_matches = tokens[0::2]
    return matches,non_matches

m,nm = split_matches(text,ab_re)
''.join(nm) # equivalent to ab_re.sub('',text)
0 голосов
/ 15 октября 2008

Вы можете использовать расщепление с захватом паразитов. Если вы это сделаете, то текст всех групп в шаблоне также будет возвращен как часть результирующего списка (из python doc ).

Таким образом, код будет

import re
ab_re = re.compile("([ab])")
text="abcdedfe falijbijie bbbb laifsjelifjl"
matches = ab_re.split(text)
# matches = ['', 'a', '', 'b', 'cdedfe f', 'a', 'lij', 'b', 'ijie ', 'b', '', 'b', '', 'b', '', 'b', ' l', 'a', 'ifsjelifjl']

# now extract the matches
Rmatches = []
remaining = []
for i in range(1, len(matches), 2):
    Rmatches.append(matches[i])
# Rmatches = ['a', 'b', 'a', 'b', 'b', 'b', 'b', 'b', 'a']

for i in range(0, len(matches), 2):
    remaining.append(matches[i])
remainingtext = ''.join(remaining)
# remainingtext = 'cdedfe flijijie  lifsjelifjl'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...