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

2024-04-18 02:28:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我遇到了一个可能遇到“{key”或“{key\n”的情况,我希望将“{key\n”转换为“{key”,而不影响字符串中“\n”的其他实例。键可以包含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是从哪里来的?你知道吗

  • 很明显,下划线在被替换时是匹配的
  • 在帕伦家,所以在第一组
  • 第1组是在替换中出现的(无下划线)

Tags: 实例key字符串testimportrefoosq
2条回答

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

\{*匹配0个或多个文字{。在本例中,因为它期望下一个字符是_a-zA-Z0-9-后面跟一个\n,所以它捕获了\n前面的最后一个字符,并有效地使\{*语句不相关。你知道吗

然后,由于\n与另一个字符一起包含在捕获组中,当您用\1反向引用替换它时,换行符将与另一个字符一起包含在替换组中。在本例中,您将用空格替换_\n,这就是空格消失的原因。你知道吗

这就得到了包括下划线在内的答案—如果要替换换行符,需要将其从捕获组中排除。另外,愚蠢的我,我错过了在backreference中缺少文本字符串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); 

您犯了两个错误,捕获了\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所述,您可以用\w替换a-zA-Z0-9_,这样您就可以简化为:

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

相关问题 更多 >