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 に答える