2011-01-13 2 views
2

Учитывая строковое преобразование, выраженное как подстановка регулярного выражения, есть ли удобный способ отменить это преобразование, желательно в python?reverse a regexp substitution

Например, если преобразование

def f(x): return re.sub('foo((:?bar)?)', r'\1', x) 

который превращает 'foobar' в 'bar' и 'foo' в пустую строку, я хотел бы получить

def g(x): return re.sub('((:?bar)?)', r'foo\1', x) 

, который делает обратное, в том смысле, что

f(g(x)) == x 

Очевидно, что не все регулярные выражения являются отображением 1: 1, но мое желаемое за действительное состоит в том, что все они могут быть отменены в смысле получения одного возможного входного значения g(x), которое даст заданный результат x из первоначальной подстановки.

Зачем мне это нужно? Я хотел бы генерировать URL-адреса для произвольных путей файловой системы на основе разбора директив AliasMatch в конфигурационном файле Apache.

+1

+1 для очень интересной проблемы, но я сомневаюсь, что есть приемлемое решение, которое даже отдаленно надежно. – delnan

ответ

0

Ну, практически то, что происходит в этом примере:

xy? -> $1 
y? -> x$1 

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

+0

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

2

Ваш пример не работает; ('(bar)?', 'foo$1') не является обратной стороной ('foo(bar)?', '$1').

Если попробовать (опуская замену группы на данный момент):

import re 
re.sub(r'(bar)?', 'foo', 'xyz') 

вы получаете fooxfooyfoozfoo.

Это потому, что (bar)? соответствует нулевой строке, а пустая строка существует в каждом возможном месте в строке.

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

(я бросил группу выше, потому что на самом деле не работает в Python. Если вы re.sub(r'(bar)?', r'foo\1', 'xyz'), он будет терпеть неудачу с исключением, если (bar)? был пропущен. Вы можете исправить это с ((bar)?), так что внешняя группировка никогда но это связано с вашей проблемой.)

+0

Спасибо за подсказки. Я исправил пример, как вы предложили. Теперь, передавая «fooxfooyfoozfoo» в исходную подстановку, возвращает меня «xyz''». Таким образом, я думаю, что «fooxfooyfoozfoo» - приемлемый результат ... – slowdog