2016-08-19 54 views
4

在我的文本中,我想用兩個空格替換所有前導製表符,但保留單獨的非前導製表符。使用單個替換操作替換所有帶空格的前導製表符

例如:

a 
\tb 
\t\tc 
\td\te 
f\t\tg 

"a\n\tb\n\t\tc\n\td\te\nf\t\tg"

應該變成:

a 
    b 
    c 
    d\te 
f\t\tg 

"a\n b\n c\n d\te\nf\t\tg"

對於我來說,我能做到這一點與多個替換操作,重複許多次數的最大值嵌套級別或直到沒有任何變化。

但是,在單次運行中是不是也可以做到這一點?

我試過,但沒能拿出的東西,我想出了但最好是用lookarounds:

re.sub(r'(^|(?<=\t))\t', ' ', a, flags=re.MULTILINE) 

其中「唯一」,使得一個錯誤的更換(fg之間的第二個選項卡)。

現在可能是因爲已經被替換的零件不能再次匹配(或者說替換不會立即發生),因此在單次運行中根本無法在正則表達式中執行,而且您無法進行排序在正則表達式中「計數」,在這種情況下,我希望看到一些關於爲什麼的更詳細的解釋(只要這不會轉移到[cs.se]領域)。

我目前在Python工作,但這可能適用於幾乎任何類似的正則表達式實現。

+1

爲什麼不只是'.strip()'每行? – jonrsharpe

+0

@jonrsharpe:我想替換'\ t's,而不是刪除它們。 – phk

回答

8

您可以在線路的開始匹配的標籤,並使用lambda內re.sub有雙位乘以本場比賽的長度來代替:

import re 
s = "a\n\tb\n\t\tc\n\td\te\nf\t\tg"; 
print(re.sub(r"^\t+", lambda m: " "*len(m.group()), s, flags=re.M)) 

Python demo

1

另外,也可以在一個襯墊使用replace()這樣做沒有正則表達式:

>>> s = "a\n\tb\n\t\tc\n\td\te\nf\t\tg" 
>>> "\n".join(x.replace("\t"," ",len(x)-len(x.lstrip("\t"))) for x in s.split("\n")) 
'a\n b\n c\n d\te\nf\t\tg' 
1

這這裏是有點CRA zy,但它的工作原理:

"\n".join([ re.sub(r"^(\t+)"," "*(2*len(re.sub(r"^(\t+).*","\1",x))),x) for x in "a\n\tb\n\t\tc\n\td\te\nf\t\tg".splitlines() ])