2014-08-30 1 views
2

Я хочу, чтобы иметь возможность генерировать 'foos, bars and bees' от 'foo, bar and bee' с использованием re.sub.Регулярное выражение Python для добавления символа ко всем словам в строке за исключением и

Я даже не могу просто добавить 's' ко всем словам для работы. Я буду работать над исключением «и», как только я получу эту часть. Я пробовал subbing \b с "s", но это соответствует началу и концу слов. Если я использую '\w*\b', тогда все слово заменяется. Я пытаюсь понять это, используя документы Python, и (?P) или (?<=...). Утверждения lookbehind кажутся такими, какими они могут быть для меня, но мне трудно заставить их сотрудничать, а примеры ограничены.

+0

Как насчет разделить строку на список слов, фильтровать ands, добавить s и затем присоединиться? – user3885927

+0

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

ответ

4

Это работает, основанный на замене принимающей вызываемый:

re.sub('(\w+)', lambda m: m.group(1) + 's' if m.group(1) != 'and' else 'and', 'foo, bar and bee') 

Он был вдохновлен an old bug report (второй к последней записи).

EDIT: Чем короче и, возможно, более читаемым решение:

re.sub('(and)|(\w+)', lambda m: m.group(1) or m.group(2) + 's', 'foo, bar and bee') 

Он также имеет преимущество, что делает его легче добавить другие слова в список исключений, так как isedev предложил в комментарии.

+3

, если вы измените: 'm.group (1)! = 'И' else 'и' 'на' m.group (1) не в (' и ',) else m.group (1) ', тогда это легко чтобы расширить до слов, чтобы игнорировать ... но мне это нравится. – isedev

+0

@isedev Да, определенно. Я просто добавил другое решение, которое также легко расширить, немного короче и без повторений 'm.group (1)' и 'and'. –

+0

Мне нравится сила использования выражения лямбды. Это указывало на меня в том направлении, в котором я кончался. –

2

Не считая слов, чтобы исключить следующее добавит «S» до конца всех слов в строке:

re.sub('([a-zA-Z]+)','\\1s','foo, bar and bee') 
-> 'foos, bars ands bees' 

Для pluralise слов в более общем и менее подвержен ошибкам образом, вы могли бы хочу взглянуть на пакет inflect (для английского как минимум).

+0

Спасибо. Я знаю об инфляции, но не нуждаюсь в ней для этой задачи, у которой есть фиксированный набор входов, где добавление s выполняет задание –

+0

Любые предложения по исключению * и *? Я взял то, что вы мне дали, и попробовал несколько вещей, и, похоже, это не так прямо, как я надеялся. –

+0

Я не могу придумать разумный способ сделать это с помощью регулярного выражения. – isedev

2

Ниже код будет добавить s все слова, кроме слова and,

>>> import re 
>>> s = "foo, bar and bee " 
>>> m = re.sub(r'(?!and)(\b\w+\b)', r'\1s', s) 
>>> m 
'foos, bars and bees ' 

Отрицательный опережения утверждает, что она будет соответствовать один или несколько символов слова, но не \band\b. \b здесь означает границу слова, которая совпадает между символом слова и символом, отличным от слова.

+0

Вы говорите о '\ band \ b', но это не то, что здесь происходит.Например, 'android' также будет исключен (даже если он не соответствует' \ band \ b'). – seb

+0

нет, op означает, что это не так. Если у вас есть какие-либо разъяснения, обратитесь к оп. –