2016-04-22 89 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'"