【问题标题】:Regex to exclude string and attribute within expression正则表达式在表达式中排除字符串和属性
【发布时间】:2016-03-09 06:53:14
【问题描述】:

我有一个正则表达式,当表达式为{{ function() }}{{ object.function() }} 或像{{ a+b }} 这样的算术运算时,它会将{{ expression }} 转换为{% print expression %},但当它得到{{ var }}{{ object.attribute }} 时不会转换。

我遇到的正则表达式的问题是将字符串表达式{{ "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 }} {{ object.var }} {%print func()%} {% print object.function() %} {% print a+b %} {% print "string" %} {% print "{{ var }}" %} {% print "function()" %} {% print "a+b" %}'

我想要的输出是:

'{{ var }} {{ object.var }} {%print func()%} {% print object.function() %} {% print a+b %} {{ "string" }} {{ "{{ var }}" }} {{ "function()" }} {{ "a+b" }}'

注意:这里的一个条件是{{ }}之间的表达式可以有字符串表达式,如{{ "string" }},即带双引号或{{ 'string' }},即带单引号。

【问题讨论】:

  • 大概是因为您在角色组中使用了\w。您可以使用\" 在此处添加双引号,或者不使用正则表达式并测试"()" 是否在val.group(1) 中(以及其他类似+-*/ 的内容)。
  • 我不能只检查“()”这个因为我想转换算术表达式也像 {{ a+b }} 如果我要检查“()”它也会转换表达式像 {{ "function()" }}。我只想转换 {{ function () }} 或 {{ a+b }} 而不是像 {{ "function()" }} {{ "a + b" }} 这样的表达式
  • 也许最直接的方法是为包围(双)引号或包围双括号添加大小写。或者找一个模板转换器,它已经可以做你想做的事情。

标签: python regex string algorithm


【解决方案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))

为字符串添加了高级屏蔽,因此 "\""'"' 将被识别为字符串,假设变量永远不能仅包含 _。字符串 start 和 endcharacter 位于变量 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 %}

【讨论】:

  • 你的答案很对,但在这种模式下,我们只能寻找包含加法符号的算术表达式。我们不能只解析减法、乘法、取模或除法 {{a + b }} 将是 {% print a+b %} 而不是 {{ a+b*cd/100}} 或 {{ 1 * 2 } } 或 {{ 20 - 10}} 等我们还想将它们转换为 {% print算术运算 %} 除非它们不是像 {{ "1 * 2" }} 等这样的字符串。
  • @yashlodha {{ a+b*c-d/100}} 在我的解决方案中也转换为 {% print a+b*c-d/100 %} 您提到的另一个。字符串 {{ "1 * 2" }} 被转换为 {{ "1 * 2" }}。那么问题出在哪里?
  • {{ 1 * 2 }} 成 {% print 1 * 2 %} 或 {{ 20/10 }} 成 {% print 20/10%} 或 {{ 5-4 }} 成{% 打印 5-4 %}。
  • @yashlodha 更新了我的答案,它现在适用于您的示例。变量名的语法是什么?也许可以直接替换 \w 而无需通过语法定义
  • 我还必须确保如果我有 {{ "string"|filter }} 它将更改为 {% "string"|filter %}
猜你喜欢
  • 2017-04-13
  • 2012-02-17
  • 1970-01-01
  • 2021-09-16
  • 1970-01-01
  • 1970-01-01
  • 2020-04-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多