【问题标题】:How to use regex to identify posts by different people on a forum?如何使用正则表达式来识别论坛上不同人的帖子?
【发布时间】:2019-06-24 07:05:39
【问题描述】:

我正在尝试使用正则表达式来识别不同学生的帖子。

帖子始终采用以下形式:

“U3951583\n 你好,我的名字是 Harry。查看 http://www.harryresume.com。那是我的网站。 \n U39501492\n 那是 很酷的网站。 \n U5235098\n 我也去看看”

  1. 因此学生证可以是 7-8 个数字。
  2. 学生可以发帖 任何事物。单词、数字、标点符号等。
  3. 我们不知道有多少 帖子将有多少人。

如何使用正则表达式创建一个列表,其中的元素是每个学生按发布顺序发布的帖子。

学生可以发布任何内容,所以我使用 [\s\S]+ 来捕捉它。我的尝试是:re.findall('(U\d+\n[\s\S]+?)',text)。然而,这只返回学生的 ID 而不是他们的文本:['U3951583\n ', 'U39501492\n ', 'U5235098\n ']

在这种情况下如何使用正则表达式匹配?

【问题讨论】:

  • 确切的 Python 版本是什么?
  • Python 3.6.8(默认,2019 年 1 月 14 日,11:02:34)
  • 可能是你的非贪心匹配模式不够贪心。
  • 请检查下面的答案,如果有任何适合您的方法,或者您需要更多帮助/说明,请告知。

标签: python regex python-3.x


【解决方案1】:

您可以使用re.findall 方法:

import re
txt = "U3951583\n Hi there my name is Harry. Check out http://www.harryresume.com. That's my website. \n U39501492\n That's a cool website. \n U5235098\n I'll have a look too"
print(re.findall(r'\bU\d{7,8}\b.*?(?=\bU\d{7,8}\b|\Z)', txt, re.S))
# => ["U3951583\n Hi there my name is Harry. Check out http://www.harryresume.com. That's my website. \n ", "U39501492\n That's a cool website. \n ", "U5235098\n I'll have a look too"]

Python demo

分别获取名称和内容的变体:

for name, content in re.findall(r'\b(U\d{7,8})\b(.*?)(?=\bU\d{7,8}\b|\Z)', txt, re.S):
    print("{}:{}".format(name.strip(), content.strip()))

输出:

U3951583:Hi there my name is Harry. Check out http://www.harryresume.com. That's my website.
U39501492:That's a cool website.
U5235098:I'll have a look too

this Python demo

使用的正则表达式是

\b(U\d{7,8})\b(.*?)(?=\bU\d{7,8}\b|\Z)

regex demo

详情

  • \b - 单词边界(没有字母/数字/_ 可以立即出现在当前位置的左侧)
  • (U\d{7,8}) - 第 1 组:U 和 7 位或 8 位数字
  • \b - 单词边界
  • (.*?) - 第 2 组:任何 0+ 个字符,尽可能少
  • (?=\bU\d{7,8}\b|\Z) - 正向前瞻,要求上述模式(名称模式)紧邻当前位置的右侧或 (|) 字符串结尾 (\Z)。

Python 3.7+

在最新的 Python 版本中,您可以使用与空字符串匹配的模式 re.split

>>> import re
>>> txt = "U3951583\n Hi there my name is Harry. Check out http://www.harryresume.com. That's my website. 
\n U39501492\n That's a cool website. \n U5235098\n I'll have a look too"
>>> print(re.split(r'(?!^)(?=\bU\d{7,8}\b)', txt))
["U3951583\n Hi there my name is Harry. Check out http://www.harryresume.com. That's my website. \n ", "U3
9501492\n That's a cool website. \n ", "U5235098\n I'll have a look too"]

因此,如果您不需要单独获取名称和内容,这可能是一种更简单的方法。

【讨论】:

  • @AbdulNiyasPM 所有解释都已添加。
  • 能否请您解释一下 re.split 示例中的 (?!^)?
  • @SarahHolder (?!^) = 不在字符串的开头
【解决方案2】:

您可以匹配 U 和 7-8 位数字,然后是不以相同模式开头的行。

\bU\d{7,8}(?:\r?\n(?![ ]*U\d{7}).*)*

说明

  • \bU\d{7,8}字边界,匹配U后跟7-8位数字
  • (?:非捕获组
    • \r?\n匹配换行符
    • (?! 负前瞻,断言右边的不是
      • [ ]*\bU\d{7} 匹配 0+ 次空格,后跟单词边界、U 和 7 位数字
    • ).* 关闭负前瞻并匹配任何字符 0+ 次
  • )* 关闭非捕获组并重复 0+ 次以匹配以下所有行

例如

import re

s = "U3951583\n Hi there my name is Harry. Check out http://www.harryresume.com. That's my website. \n U39501492\n That's a cool website. \n U5235098\n I'll have a look too"
regex = r"\bU\d{7,8}(?:\r?\n(?![ ]*U\d{7}).*)*"

print(re.findall(regex, s))

结果

["U3951583\n Hi there my name is Harry. Check out http://www.harryresume.com. That's my website. ", "U39501492\n That's a cool website. ", "U5235098\n I'll have a look too"]

Regex demo | Python demo

【讨论】:

    【解决方案3】:

    尝试使用这个正则表达式:

    \d{7,8}
    

    Here Is Demo

    祝你好运!

    【讨论】:

      猜你喜欢
      • 2015-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多