使用单个替换操作将所有前导选项卡替换为空格

时间:2016-08-19 11:58:45

标签: python regex

在我的文字中,我想用两个空格替换所有前导标签,但只保留非前导标签。

例如:

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"

对于我的情况,我可以通过多次替换操作来执行此操作,重复与许多最大嵌套级别一样多次,或者直到没有任何更改。

但是一次运行也不可能吗?

我尝试了但是没有设法提出一些东西,我提出的最好的东西是外观:

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

哪个“仅”进行了错误的替换(fg之间的第二个标签)。

现在可能在单次运行中根本无法进行正则表达式,因为已经更换的部件无法再次匹配(或者更换不会立即发生)并且您无法排序“计算“在正则表达式中,在这种情况下,我希望看到一些更详细的解释为什么(只要这不会转移到[cs.se]领域)。

我目前正在使用Python,但这几乎适用于任何类似的正则表达式实现。

3 个答案:

答案 0 :(得分:8)

您可以匹配行开头的标签,并使用re.sub内的lambda替换为双倍空格乘以匹配的长度:

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 :(得分: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'

答案 2 :(得分:1)

这有点疯狂,但它有效:

"\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() ])