Простая замена строки - PullRequest
       22

Простая замена строки

0 голосов
/ 20 октября 2008

Какой самый простой способ для меня преобразовать более простой формат регулярного выражения, к которому привыкло большинство пользователей, в правильную строку регулярного выражения re Python?

В качестве примера мне нужно преобразовать это:

string = "*abc+de?"

к этому:

string = ".*abc.+de.?"

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

Ответы [ 5 ]

5 голосов
/ 20 октября 2008

Они не похожи на регулярные выражения, которые вы пытаетесь перевести, они больше похожи на глобусы оболочки Unix. В Python уже есть модуль для этого. Он не знает о синтаксисе «+», который вы использовали, но и моя оболочка не знает, и я думаю, что синтаксис нестандартный.

>>> import fnmatch
>>> fnmatch.fnmatch("fooabcdef", "*abcde?")
True
>>> help(fnmatch.fnmatch)
Help on function fnmatch in module fnmatch:

fnmatch(name, pat)
    Test whether FILENAME matches PATTERN.

    Patterns are Unix shell style:

    *       matches everything
    ?       matches any single character
    [seq]   matches any character in seq
    [!seq]  matches any char not in seq

    An initial period in FILENAME is not special.
    Both FILENAME and PATTERN are first case-normalized
    if the operating system requires it.
    If you don't want this, use fnmatchcase(FILENAME, PATTERN).

>>> 
2 голосов
/ 20 октября 2008

.replacing () каждый из подстановочных знаков - быстрый способ, но что, если подстановочная строка содержит другие специальные символы регулярного выражения? например. кто-то ищет «my.thing *», вероятно, не означает, что «.» соответствовать любому персонажу. И в худшем случае такие вещи, как скобки, создающие группу совпадений, могут нарушить вашу окончательную обработку совпадений с регулярным выражением.

re.escape можно использовать для помещения буквенных символов в регулярные выражения. Вы должны будете сначала выделить символы подстановки. Обычный трюк для этого - использовать re.split с соответствующей скобкой, в результате чего получается список в форме [literal, wildcard, literal, wildcard, literal ...].

Пример кода:

wildcards= re.compile('([?*+])')
escapewild= {'?': '.', '*': '.*', '+': '.+'}

def escapePart((parti, part)):
    if parti%2==0: # even items are literals
        return re.escape(part)
    else: # odd items are wildcards
        return escapewild[part]

def convertWildcardedToRegex(s):
    parts= map(escapePart, enumerate(wildcards.split(s)))
    return '^%s$' % (''.join(parts))
1 голос
/ 20 октября 2008

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

Вам необходимо сгенерировать список замен, которые необходимо преобразовать из "пользовательского формата" в регулярное выражение. Для простоты обслуживания я бы сохранил их в словаре, и, как @Konrad Rudolph, я бы просто использовал метод замены:

def wildcard_to_regex(wildcard):
    replacements = {
        '*': '.*',
        '?': '.?',
        '+': '.+',
        }
    regex = wildcard
    for (wildcard_pattern, regex_pattern) in replacements.items():
        regex = regex.replace(wildcard_pattern, regex_pattern)
    return regex

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

(Кроме того, я не уверен, что ? должно переводиться на .? - я думаю, что нормальные символы подстановки имеют ? как "ровно один символ", поэтому его замена должна быть простой . - но я следую вашему примеру.)

0 голосов
/ 20 октября 2008

Вот пример Perl , делающий это. Он просто использует таблицу для замены каждой подстановочной конструкции соответствующим регулярным выражением. Ранее я делал это сам, но в Си не должно быть слишком сложно портировать на Python.

0 голосов
/ 20 октября 2008

Я бы использовал replace:

def wildcard_to_regex(str):
    return str.replace("*", ".*").replace("?", .?").replace("#", "\d")

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...