Python正则表达式:搜索和替换怪异

时间:2010-09-22 13:29:03

标签: python regex replace

我真的可以在Python正则表达式问题上使用一些帮助。你期待

的结果
import re
re.sub("s (.*?) s", "no", "this is a string") 

是“这不是字符串”,对吗?但实际上它是“瘦身”。子函数使用整个模式作为要替换的组,而不仅仅是我实际想要替换的组。

所有re.sub示例都涉及简单的单词替换,但如果您想根据字符串的其余部分更改某些内容,该怎么办?就像我的例子......

非常感谢任何帮助。

编辑:

在我的情况下,后视和前瞻技巧不起作用,因为那些需要固定宽度。这是我的实际表达:

re.sub(r"<a.*?href=['\"]((?!http).*?)['\"].*?>", 'test', string)

我想用它来查找字符串中不以http开头的所有链接,所以我可以在这些链接前加一个前缀(使它们绝对而不是相对)。

5 个答案:

答案 0 :(得分:5)

你的正则表达式匹配从第一个s到最后一个s的所有内容,所以如果用“no”替换匹配,你就会得到“thinotring”。

括号不限制匹配,它们在称为反向引用的特殊变量中捕获与其内部匹配的文本。在您的示例中,反向引号1将包含is a。您可以使用反斜杠和后向引用的数量来引用同一正则表达式中的反向引用:\1

你可能想要的是环顾问题:

re.sub(r"(?<=s ).*?(?= s)", "no", "this is a string")

(?<=s )表示:断言可以在字符串中的当前位置之前匹配s,但不要将其作为匹配的一部分。

(?= s)相同,但它断言字符串将在当前位置后继续s

请注意,Python中的lookbehind仅限于固定长度的字符串。因此,如果这是一个问题,您可以使用... backreferences 来解决这个问题!

re.sub(r"(s ).*?( s)", r"\1no\2", "this is a string")

好的,这是一个人为的例子,但它显示了你可以做的事情。从您的编辑开始,您正在尝试使用正则表达式解析HTML。现在这不是一个好主意。搜索SO“regex html”,你会明白为什么。

如果您仍想这样做:

re.sub(r"(<a.*?href=['"])((?!http).*?['"].*?>)", r'\1http://\2', string)

可能会奏效。但这非常脆弱。

答案 1 :(得分:1)

使用(?<=...)(?=...)匹配部分字符串但不替换它们:

re.sub("(?<=s )(.*?)(?= s)", "no", "this is a string")

编辑:这会返回this no string,所以不是你想要的......: - (

有关更新的问题,请尝试以下操作:

re.sub(r"(?<=href=['\"])((?!http).*?)(?=['\"].*?>)", 'test', string)

在链接之前检查href="是不够的?

答案 2 :(得分:1)

你的表情,虽然讨厌看起来确实有效,但是你没有捕获re.sub的结果,返回被替换的字符串,并且不对作为参数传递的字符串执行替换。

import re

new_string = re.sub(r"<a.*?href=['\"]((?!http).*?)['\"].*?>", 'test', string)
print new_string

在IDEone.com上查看:http://ideone.com/ufaTw

顺便说一句,你可能最好使用Beautiful Soup或类似系统搜索和替换HTML,使用正则表达式是一个坏主意。

答案 3 :(得分:0)

这是一个非常标准的正则表达式系统 - 它唯一的问题是语法比Perl更加冗长。 ○: - )

另一种选择是使用[^&gt;] *代替。*,因为您只需要包含在单个链接中的结果。如果你有一个有多个href的链接(据我所知不应该发生),那可能会失败,但否则它会起作用。

答案 4 :(得分:-1)

好的,环顾四周是可能的,只需要一个小的重写。这有效:

def absolutize(string, prefix):
    return re.sub(r"(?<=href=['\"])((?!http).*?)(?=['\"])", prefix+r'\1', string)

仍然是愚蠢的Python正则表达式系统...... :(