未能找到' - <'使用正则表达式的子串

时间:2013-04-24 15:04:13

标签: regex python-3.x

以下是目标字符串。

July 17, 2007 –<br> September 25, 2009 <br> June 2007 - July 2010

我正在尝试在<br>代码之前添加换行符,但不跟随-。因此,结果字符串应为:

July 17, 2007 –<br> September 25, 2009 \n<br> June 2007 - July 2010

我尝试了以下正则表达式无济于事。

re.sub(r'([^-])(\s*<br)',r'\1\n\2', astring)

给了我

July 17, 2007 –\n<br> September 25, 2009\n <br> June 2007 - July 2010

解决方案是什么?

更新:

我实际上并不是用正则表达式解析HTML。我知道HTML + RegEx组合会让我陷入精神错乱。 我正在使用lxml解析HTML。 但是,我无法理解的是为什么正则表达式无法捕获-\s*<模式。

2 个答案:

答案 0 :(得分:4)

文字中的短划线字符为EN DASH U+2013,这就是([^-])EN DASH匹配并进行替换的原因。

您需要将角色添加到角色类中,并将\s*移动到第一个捕获组,并将\s添加到否定角色类,以使其按您的需要工作:

re.sub(r'([^\s–-]\s*)(<br)',r'\1\n\2', astring)

请注意,虽然上面的代码有效,但它不可维护 - 因为很难注意到字符类中的EN DASH

Python 3.3及更高版本添加了\u\U Unicode转义序列。您可以这样指定正则表达式:

re.sub(r'([^\s\u2013-]\s*)(<br)',r'\1\n\2', astring)

可以说\u2013是什么不明确,但至少,代码的读者不会被绊倒。

对于Python 3.2及更低版本,您可以使用普通文字字符串而不是原始文字字符串语法来实现相同的效果。

re.sub('([^\\s\u2013-]\\s*)(<br)',r'\1\n\2', astring)

从技术上讲,由于Python解析文字字符串的方式(如果它不形成有效的转义序列,则保留\),'([^\s\u2013-]\s*)(<br)'也有效(比较\\s和{{1但是,为了安全,我将逃生加倍。

答案 1 :(得分:1)

字符串中的和正则表达式中的-字符不同。尝试

re.sub(r'([^–])(\s*<br)',r'\1\n\2', astring)