2016-03-09 2 views
4

У меня есть регулярное выражение, которое будет преобразовывать {{ expression }} в {% print expression %} когда выражение {{ function() }} или {{ object.function() }} или арифметическая операция, как {{ a+b }}, но не будет конвертировать, когда он получит {{ var }} или {{ object.attribute }}.Regex исключить строку атрибутов и в выражении

Проблема с регулярным выражением у меня есть, это преобразовать строковое выражение {{ "string" }} или {{ "function()" }} или {{ "{{ var}}" }} в {% print "string" %} или {% print "function()" %} или {% print "{% print var %}" %}

import re 

def replacement(val): 
    content = val.group(1) 
    if re.match('^\s*[\w\.]+\s*$', content): 
     return "{{%s}}" % content 
    else: 
     return "{%% print %s %%}" % content 

string_obj = """{{ var }} {{ object.var }} {{ func()}} {{ object.function() }} {{ a+b }} {{ "string" }} {{ "{{ var }}" }} {{ "function()" }} {{ "a+b" }}""" 

print(re.sub("{{(\s*.*?\s*)}}", replacement, string_obj)) 

Выход:

«{{вар}} {{объект .var}} {% print func()%} {% print object.function()%} {% print a + b%} {% print "строка"%} {% print "{{var}}"% } {% print "function()"%} {% p ечать "а + Ь" %} '

Вывод, что я хочу это:

' {{вар}} {{object.var}} {% распечатать FUNC()%} { % print object.function()%} {% print a + b%} {{"string"}} {{"{{var}}"}} {{"function()" }} {{a + Ь»}}»

Примечание: Единственное условие здесь выражение между {{ }} может иметь строковое выражение как {{ "string" }}, т. Е. С двойными кавычками или {{ 'string' }} т. Е. С одинарными кавычками.

+0

Предположительно, это происходит потому, что вы используете '\ w' в группе символов. Вы можете либо добавить двойные кавычки туда с '\" ', либо не использовать регулярное выражение и проверить, является ли' '()" 'в' val.group (1) '(и что-нибудь еще, как' + - */'). – Evert

+0

Я не могу проверить только«() », потому что я хочу преобразовать арифметическое выражение также как {{a + b}}, и если я проверю«() », он также преобразует выражение, подобное { {"function()"}} Я хочу только преобразовать {{function()}} или {{a + b}} не выражение, как {{"function()"}} {{"a + b"}} –

+0

Возможно, самый простой способ - добавить случаи для окружающих (двойных) котировок или близких двойных фигурных скобок. Или найти конвертер шаблонов, который уже делает то, что вы пытаетесь сделать. – Evert

ответ

1

Код

Для печати красивее я просто раздеть пробелы в начале и в конце. Это просто упрощает регулярное выражение.

import re 

def replacement(val): 
    content = val.group(1).strip() 
    if re.match('^\w[^\.\(\+\*\/\-\|]*\.?\w[^\.\(\+\*\/\-\|]*$', content): 
     return "{{ %s }}" % content 
    else: 
     return "{%% print %s %%}" % content 

def maskString(templateString): 
    stringChars = ['"', "'"] 
    a = 0 
    start = None 
    maskedList = [] 
    while a < len(templateString): 
     l = templateString[a] 
     if l in stringChars and start is None and a-1 >=0 and templateString[a-1] != '\\': 
      start = {'l' : l, 's' : a} 
     elif start is not None and l is start['l'] and a-1 >=0 and templateString[a-1] != '\\': 
      start['e'] = a + 1 
      stringToMask = templateString[start['s']:start['e']] 
      templateString = templateString[:start['s']] + ("_" * len(stringToMask)) + templateString[start['e']:] 
      maskedList.append(stringToMask) 
      start = None 
     a += 1 
    return (templateString, maskedList) 

def unmaskString(templateString, maskedList): 
    for string in maskedList: 
     templateString = templateString.replace("_" * len(string), string,1) 
    return templateString 

def templateMatcher(templateString): 
    p = re.compile('("[^"]*)"') 
    templateString, maskedList = maskString(templateString) 
    templateString = re.sub("{{(\s*.*?\s*)}}", replacement, templateString) 
    return unmaskString(templateString, maskedList) 

string_obj = """{{ var }} {{ object.var }} {{ func()}} {{ object.function() }} {{ a+b }} {{ "string" }} {{ "{{ var }}" }} {{ "function()" }} {{ "a+b" }}""" 
string_obj_2 = """{{ a+b*c-d/100}} {{ 1 * 2 }} {{ 20/10 }} {{ 5-4 }}""" 
string_obj_3 = """{{ "another {{ mask" }} {{ func() }}, {{ a+b }} , {{ "string with \\""|filter }}""" 

print(templateMatcher(string_obj)) 
print(templateMatcher(string_obj_2)) 
print(templateMatcher(string_obj_3)) 

Добавлена ​​расширенная маскировка для строк так "\"" и '"' будет признан в качестве строки, при условии, что переменное никогда не состоит только из _. Начальные и конечные элементы строк находятся в переменной stringChars. Поэтому, если вам не нравится ', просто удалите его оттуда.

Выход

{{ var }} {{ object.var }} {% print func() %} {% print object.function() %} {% print a+b %} {{ "string" }} {{ "{{ var }}" }} {{ "function()" }} {{ "a+b" }} 
{% print a+b*c-d/100 %} {% print 1 * 2 %} {% print 20/10 %} {% print 5-4 %} 
{{ "another {{ mask" }} {% print func() %}, {% print a+b %} , {% print "string with \""|filter %} 
+0

ваш ответ совершенно прав, но в этом шаблоне мы можем только найдите арифметическое выражение, которое содержит символ добавления содержимого.мы не можем анализировать субимость, умножение, по модулю или делению только {{a + b}} будет {% print a + b%} not {{a + b * cd/100}} или {{1 * 2} } или {{20 - 10}} и т. д. мы также хотим преобразовать их в {% print arithmetic_operation%}, если они не являются строками типа {{"1 * 2"}} и т. д. –

+0

@yashlodha '{{a + b * cd/100}} 'находится в моем решении, преобразованном в' {% print a + b * cd/100%} 'другой, как вы упомянули, тоже. Строка '{{" 1 * 2 "}}' преобразуется в {{"1 * 2"}}. Итак, где проблема? – Kordi

+0

{{1 * 2}} в {% print 1 * 2%} или {{20/10}} в {% print 20/10%} или {{5-4}} в {% print 5-4% }. –

Смежные вопросы