正则表达式字符串替换:如果backref为空,则省略逗号

时间:2016-04-22 08:37:48

标签: python regex sed ansible backreference

我想使用一个匹配并替换

的正则表达式+ backref-expression 带有text = 'a,b,c'

text = 'a,b,c,item_1'

text = '' text = 'item_1'

text = 'a'text = 'a,item_1'

  1. 我一般对使用sed但使用python regex的解决方案感兴趣。

  2. 特别是,我正在寻找一个与lineinfile({3}}(python)的Ansible模块一起使用的解决方案。

  3. 这是我到目前为止(在Ansible中):

    regexp:   "^(text[ ]*=[ ]*')([^']*)(')"
    backrefs: yes
    line:     '\1item_1,\2\3'
    

    编辑:如果可能,regex + backref-ex对应忽略已存在的item_1,即"替换"

    text = 'item_1' text = 'item_1'

    text = 'a,item_1' text = 'a,item_1'

    text = 'a,d,x'text = 'a,item_1,x'

3 个答案:

答案 0 :(得分:1)

您可以使用

^(text[ ]*=[ ]*')((?:[^',]*(,?)[^']*)?[^']*)(')

请参阅regexPython demo

import re
r = re.compile(r"^(text[ ]*=[ ]*')((?:[^',]*(,?)[^']*)?[^']*)(')")
print(r.sub(r"\1\2\3d\4", "text = 'a,b,c'")) # => text = 'a,b,c,d'
print(r.sub(r"\1\2\3d\4", "text = ''"))      # => text = 'd'

我所做的只是插入(?:[^',]*(,?)[^']*)?子模式以选择性地捕获逗号。如果它出现在字符串中,则在d之前插入此逗号。如果不是,则不插入逗号。

<强>更新

您可以将任务拆分为两个操作:

或Python解决方案

import re
p = re.compile(r'^(text[ ]*=[ ]*\')([^\']*)(\')')
strs = ["text = 'a,b,c'", "text = 'a'", "text = ''"]
print([p.sub(lambda x: x.group(1) + (x.group(2) + ",d" if x.group(2) else "d" ) + x.group(3), s) for s in strs])

请参阅IDEONE demo

答案 1 :(得分:1)

这在sed(在awk中可能)很难做到,因为sed中没有替换回调功能。

以下回调方法应该在python中运行:

import re
reg = re.compile(r"(\btext *= *)'([^']*)'")

def repl(m):
    if len(m.group(2)) == 0:
        return m.group(1) + "'d'";
    else:
        return m.group(1) + "'" + m.group(2) + ",d'"


print(reg.sub(repl, r"text = 'a,b,c'"))
print(reg.sub(repl, r"text = ''"))
print(reg.sub(repl, r"text = 'a'"))

<强>输出:

text = 'a,b,c,d'
text = 'd'
text = 'a,d'

Code Demo

答案 2 :(得分:0)

使用负面看,我开发了一个working solution,即使它并不完美:

^(text[ ]*=[ ]*)'(((?!item_1[,]?).)*)'

如果这些正则表达式不包含要添加的项目(即item_1),则此正则表达式会抓取引号之间的所有项目。然后,backref表达式只是添加了缺少的项目:

\1'item_1,\2'

但是,解决方案并不完美,因为如果列表为空,它仍会导致尾随逗号:

text = ''            #text = 'item_1,'
text = 'a'           #text = 'item_1,a'
text = 'a,b,c,d'     #text = 'item_1,a,b,c,d'

对于我的实际案例,尾随逗号是而不是一个问题。 我通过使用another regex

添加其他lineinfile任务来修复它
regexp:    "^(text[ ]*=[ ]*)'(.*[^,])(,?)'"
backrefs:  yes
line:      "\\1'\\2'"