正则expression式replace(在Python中) – 一个更简单的方法?
任何时候我想要replace一段文本中的一部分,我总是需要做一些事情:
"(?P<start>some_pattern)(?P<replace>foo)(?P<end>end)"
然后连接start
组和replace
的新数据,然后连接end
组。
有没有更好的方法呢?
看看Python的重新文档 (?=...)
和lookbehinds (?<=...)
– 我敢肯定,他们是你想要的。 它们匹配string,但不会“消耗”它们匹配的string的位。
>>> import re >>> s = "start foo end" >>> s = re.sub("foo", "replaced", s) >>> s 'start replaced end' >>> s = re.sub("(?<= )(.+)(?= )", lambda m: "can use a callable for the %s text too" % m.group(1), s) >>> s 'start can use a callable for the replaced text too end' >>> help(re.sub) Help on function sub in module re: sub(pattern, repl, string, count=0) Return the string obtained by replacing the leftmost non-overlapping occurrences of the pattern in string by the replacement repl. repl can be either a string or a callable; if a callable, it's passed the match object and must return a replacement string to be used.
简短的版本是,你不能在使用Python的re
模块的lookbehinds中使用可变宽度的模式。 没有办法改变这个:
>>> import re >>> re.sub("(?<=foo)bar(?=baz)", "quux", "foobarbaz") 'fooquuxbaz' >>> re.sub("(?<=fo+)bar(?=baz)", "quux", "foobarbaz") Traceback (most recent call last): File "<pyshell#2>", line 1, in <module> re.sub("(?<=fo+)bar(?=baz)", "quux", string) File "C:\Development\Python25\lib\re.py", line 150, in sub return _compile(pattern, 0).sub(repl, string, count) File "C:\Development\Python25\lib\re.py", line 241, in _compile raise error, v # invalid expression error: look-behind requires fixed-width pattern
这意味着您需要解决这个问题,最简单的解决scheme与您现在正在做的非常相似:
>>> re.sub("(fo+)bar(?=baz)", "\\1quux", "foobarbaz") 'fooquuxbaz' >>> >>> # If you need to turn this into a callable function: >>> def replace(start, replace, end, replacement, search): return re.sub("(" + re.escape(start) + ")" + re.escape(replace) + "(?=" + re.escape + ")", "\\1" + re.escape(replacement), search)
这并不具备lookbehind解决scheme的优雅,但它仍然是一个非常明确,直接的一行。 如果你看一下专家在这个问题上所说的话(他在谈论JavaScript,它完全缺乏后顾之见,但是许多原则是一样的),你会发现他最简单的解决scheme看起来很像这个。
我相信最好的想法就是在一个组中捕获任何你想replace的东西,然后用捕获组的开始和结束属性replace它。
问候
阿德里安
#the pattern will contain the expression we want to replace as the first group pat = "word1\s(.*)\sword2" test = "word1 will never be a word2" repl = "replace" import re m = re.search(pat,test) if m and m.groups() > 0: line = test[:m.start(1)] + repl + test[m.end(1):] print line else: print "the pattern didn't capture any text"
这将打印:“word1永远不会是一个字2”
要被replace的组可以位于string的任何位置。
- 匿名方法(C#2.0)和lambdaexpression式(C#3.0)之间有什么区别?
- elisp正则expression式searchstring,而不是缓冲区
- jQuery从string等中删除特殊字符
- 使用正则expression式去除所有非单词字符(C#正则expression式模式中的正则expression式分隔符)
- 我如何在UNIX中对所有非ASCII字符进行grep
- 请求标题字段Access-Control-Allow-Headers在预检响应中本身不允许
- PHP正则expression式匹配HTML标签<a>外的关键字
- 用正则expression式匹配数字 – 只有数字和逗号
- PHP用一个空间replace多个空间