2016-04-22 69 views
1

我想用一个正则表达式+ backref表达匹配并替换正则表达式的字符串替换:忽略逗号如果backref是空

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. 特别是,我正在寻找与(python)的lineinfile模块一起使用的解决方案。

这里是我到目前为止(在Ansible):

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

编辑:如果可能的话,正则表达式+ 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'

+0

是一个增加另一个lineinfile任务,B和C总是单个字母,也可以是什么? –

+0

实际上,列表中的项目可以是带下划线的真实单词,但对于这个问题,我们保留单个字符。 – Juve

回答

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之前插入此逗号。如果不是,则不插入逗号。

UPDATE

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

或者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

+0

Thx对于这个第一个答案,我试了一下,发现了另一个需要覆盖的案例:用'text ='a,d''替换'text ='a''(补充说,对于这个问题) – Juve

+0

有没有办法要纯粹使用正则表达式,您需要评估捕获组的内容。原因是你不能在sed或Python're' regex风格中使用条件替换模式。你对可以处理这种情况的Python代码感兴趣吗? –

+0

我发布了一个2-regex解决方案,如果您无法访问直接的Python代码,它可能适合您。我还发布了一个基于Python的解决方案,展示如何使用lamda完全按照您的需要进行替换。不确定它可以帮助。 –

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

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

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