Python 2.6.1(OS X 10.6.8)re.sub()在组中强调行为?

时间:2015-07-26 17:47:45

标签: python regex backreference

我遇到的情况可能会遇到" {key"或" {key \ n"我想转换" {key \ n"到" {key"不影响" \ n"的其他实例在字符串中。 key可以包含a-z,A-Z,0-9,下划线,短划线中的任何一个。

我认为这会奏效,但它没有:

import re
test = '{sq-a_ foo}{sq-b_\nbar}\n{sq-c_ gluck}'
print re.sub(r'(\{*[_a-zA-Z0-9-]\n)','\1 ',test)

它返回:

{sq-a_ foo}{sq-b bar}
{sq-c_ gluck}

...有一个隐形字符0x01,右下角应该是替换字符。

期待这个:

{sq-a_ foo}{sq-b_ bar}
{sq-c_ gluck}

所以我的问题是,sq-b之后的下划线在哪里? 0x01来自哪里?

  • 显然,下划线匹配,因为它已被替换
  • 它在parens中,所以它在第1组
  • 第1组是替换中出现的内容(无下划线)

2 个答案:

答案 0 :(得分:1)

首先,让我们看看你的原始表达:

\{*匹配0个或更多文字{。在这种情况下,因为它期望下一个字符是其中一个_a-zA-Z0-9-后跟\n,所以它会在\n之前捕获 last 字符并且有效地使\{*语句无关紧要。

然后,由于\n与其他单个字符一起包含在您的捕获组中,因此当您使用\1反向引号替换它时,换行符将与其他字符一起包含在替换中。在这种情况下,您需要用空格替换_\n,这就是空间消失的原因。

这给我的答案包括下划线 - 如果你想替换换行符,你需要将它从捕获组中排除。另外,愚蠢的我,我错过了反向引用中缺少文字字符串r''前缀:

import re
test = '{sq-a_ foo}{sq-b_\nbar}\n{sq-c_ gluck}'
print re.sub(r'(\{[^}]+)\n(.+\})',r'\1 \2',test)

输出:

{sq-a_ foo}{sq-b_ bar}
{sq-c_ gluck}

另外值得注意的是 - 您可以使用\w代替a-zA-Z_来表达您的表达方式;)

所有这些都说,我认为可以更容易地实现目标:

re.sub(r'(?!\})\n', ' ', test); 

...将替换所有不在}前面的换行符实例。根据您尝试做的事情,这可能会更简单。

另一种选择是使用负面的后视:

re.sub(r'(?![\w-])(\n)', ' ', test); 

答案 1 :(得分:1)

你犯了两个错误,你抓住了\n并忘记了子字符串中的r

import re
test = '{sq-a_ foo}{sq-b_\nbar}\n{sq-c_ gluck}'
print re.sub(r'(\{*[_a-zA-Z0-9-])\n',r'\1 ',test)

此外,正如@remus所述,您可以将a-zA-Z0-9_替换为\w,以便简化为:

re.sub(r'(\{*[\w-])\n', r'\1 ', test)