Python: использование re.sub для замены нескольких подстрок несколько раз - PullRequest
3 голосов
/ 28 марта 2012

Я пытаюсь исправить текст, в котором есть некоторые очень типичные ошибки сканирования (я ошибаюсь за I и наоборот).По сути, я бы хотел, чтобы строка замены в re.sub зависела от того, сколько раз было обнаружено «I», что-то вроде этого:чтобы достичь этого?

Ответы [ 4 ]

3 голосов
/ 28 марта 2012

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

def replacement(match):
    if "I" in match.group(2):
        return match.group(1) + "l" * len(match.group(2)) + match.group(3)
    # Add additional cases here and as ORs in your regex

re.sub(r"(\w+)(II+)(\w*)", replacement, "I am stiII here.")
>>> I am still here.

(обратите внимание, что я изменил ваше регулярное выражение, чтобы повторяющиеся значения Is появлялись в одной группе)

1 голос
/ 28 марта 2012

Вы можете использовать lookaround , чтобы заменить только I s, за которыми следует или предшествует I:

print re.sub("(?<=I)I|I(?=I)", "l", "I am stiII here.")
0 голосов
/ 29 марта 2012

основываясь на ответе, предложенном DNS, я создал что-то более сложное, чтобы перехватить все случаи (или, по крайней мере, большинство из них), стараясь не добавлять слишком много ошибок:

def Irepl(matchobj):
    # Catch acronyms
    if matchobj.group(0).isupper():
        return matchobj.group(0)
    else:
        # Replace Group2 with 'l's
        return matchobj.group(1) + 'l'*len(matchobj.group(2)) + matchobj.group(3)


# Impossible to know if first letter is correct or not (possibly a name)
I_FOR_l_PATTERN = "([a-zA-HJ-Z]+?)(I+)(\w*)"
for line in lines:
    tmp_line = line.replace("l'", "I'").replace("'I", "'l").replace(" l ", " I ")
    tmp_line = re.sub("^l ", "I ", tmp_line)

    cor_line = re.sub(I_FOR_l_PATTERN, Irepl, tmp_line)

    # Loop to catch all errors in a word (iIIegaI for example)
    while cor_line != tmp_line:
        tmp_line = cor_line
        cor_line = re.sub(I_FOR_l_PATTERN, Irepl, tmp_line)

Надеюсьэто помогает кому-то еще!

0 голосов
/ 28 марта 2012

Мне кажется, вы могли бы сделать что-то вроде:

def replace_L(match):
    return match.group(0).replace(match.group(1),'l'*len(match.group(1)))

string_I_want=re.sub(r'\w+(I+)\w*',replace_L,'I am stiII here.')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...