我如何在Python中匹配以下Ruby gsub?

时间:2013-09-18 06:21:04

标签: regex python-2.7

假设我在Ruby中有以下函数,它通过每个新行的用户定义的空格数来缩进字符串。

def reindent(str, numIndent)
    return str.gsub(/(.)^/m) { |m| $1 + ("    " * numIndent) }
end

我如何使用re模仿Python中的这个函数?

我尝试了以下操作,但它没有用。

def reindent(line, numIndent):
  return re.sub(r'(.)^', r'\1' + '    ' * numIndent, line, flags=re.MULTILINE)

2 个答案:

答案 0 :(得分:1)

你应该知道Matz选择通过重命名/s修饰符(SINGLELINEDOTALL)来混淆所有人,因为它在所有其他正则表达式中用于Ruby的/mMULTILINE)修饰符(处理新行是否被.令牌视为“任何字符”)。

相反,其他哪些版本会调用/mMULTILINE修饰符(确定^$是否在行的开头/结尾处匹配,而不仅仅是在Ruby中根本不存在整个字符串的开始/结束。那些锚点总是在行的开头/结尾处匹配。

因此,要将代码从Ruby转换为Python,您需要执行

def reindent(line, numIndent):
    return re.sub(r'(.)^', r'\1' + '    ' * numIndent, line, flags=re.DOTALL|re.MULTILINE)

如果您的目标是缩进除第一个之外的所有行(这就是这样做),您可以简化正则表达式:

def reindent(line, numIndent):
    return re.sub(r'(?<!\A)^', '    ' * numIndent, line, flags=re.MULTILINE)

结果:

>>> s = "The following lines\nare indented,\naren't they?"
>>> print(reindent(s,1))
The following lines
    are indented,
    aren't they?

答案 1 :(得分:0)

改为使用反转形式:

import re
def reindent(line, numIndent):
  return re.sub(r'^(.*)', '    ' * numIndent + r'\1', line, flags=re.MULTILINE)
print(reindent("abcdefghijkl\nmnopqrstu", 1))

输出:

    abcdefghijkl
    mnopqrstu