2

我有一个字符串:

s = '&nbsp;<span>Mil<\/span><\/th><td align=\"right\" headers=\"Y0 i7\">112<\/td><td align=\"right\" headers=\"Y1 i7\">113<\/td><td align=\"right\" headers=\"Y2 i7\">110<\/td><td align=\"right\" headers=\"Y3 i7\">107<\/td><td align=\"right\" headers=\"Y4 i7\">105<\/td><td align=\"right\" headers=\"Y5 i7\">95<\/td><td align=\"right\" headers=\"Y6 i7\">95<\/td><td align=\"right\" headers=\"Y7 i7\">87<\/td><td align=\"right\" headers=\"Y8 i7\">77<\/td><td align=\"right\" headers=\"Y9 i7\">74<\/td><td align=\"right\" headers=\"Y10 i7\">74<\/td><\/tr>'

我想从字符串中提取这些数字:

112 113 110 107 105 95 95 87 77 74 74

我不是正则表达式方面的专家,所以谁能告诉我,为什么这没有返回任何匹配项:

p = re.compile(r'&nbsp;.*(>\d*<\\/td>.*)*<\\/tr>')
m = p.match(s)

我确定有一个 html/xml 解析模块可以解决我的问题,我也可以拆分字符串并处理该输出,但我真的想用 re 模块来做。谢谢!

4

4 回答 4

4
>>> r = re.compile(r'headers="Y\d+ i\d+">(\d+)<\\/td>')
>>> r.findall(s)
['112', '113', '110', '107', '105', '95', '95', '87', '77', '74', '74']
>>> 
于 2013-07-20T16:43:30.177 回答
4

您想要的所有数字都在“>”和“<”之间。所以,你可以这样做:

re.findall(">(\d+)<", s)

输出:

['112', '113', '110', '107', '105', '95', '95', '87', '77', '74', '74']

基本上,它是说获取介于“>”和“<”之间的每个数字流。然后,使用set,您只能获得唯一的。

于 2013-07-20T16:48:24.150 回答
2

其他答案给出了可以工作的正则表达式,但值得理解为什么你的正则表达式不起作用。

你所有的匹配都是贪婪的和可选的(*)。所以你的正则表达式说:

  • &nbsp;
  • 0个或多个字符的任何东西
  • 您的捕获组出现 0 次或多次
  • </tr>

“0 或多个字符的任何东西”吃掉字符串的其余部分,不为捕获组留下任何内容,并且由于它是可选的,因此成功匹配。

如果你想重新设计你的正则表达式来工作,你会想要使用.*?而不是.*匹配字符串开头的垃圾。使?匹配不贪心,因此它将匹配尽可能少的字符而不是尽可能多的字符。

于 2013-07-20T16:57:46.283 回答
1

您的表达式没有返回任何匹配项,因为我写的有点错误。而不是打印:

p = re.compile(r'&nbsp;.*(>\d*<\\/td>.*)*<\\/tr>')
m = p.match(s) 

你可能应该打印这个:

>>> p = re.compile(r'headers="Y\d+ i\d+">(\d+)<\\/td>')
>>> p.findall(s)
['112', '113', '110', '107', '105', '95', '95', '87', '77', '74', '74'] 
于 2013-07-20T16:55:32.870 回答