如何使用正则表达式和 python 限制文本提取直到特定字符

How to limit text extraction until specific character using regex and python

我有一句话:

text = "Alun-alun/NNP Jombang/NNP tepatnya/RB Depan/IN SMP/NNP 2/CDP Jombang/NNP Besok/NNP pagi/NN :/: :/: :/: Minggu/NNP"

我喜欢从标签 /IN 中提取任何单词,直到带有 /NNP 标签的最后一个单词。

到目前为止的代码可以提取Depan/IN SMP/NNP 2/CDP Jombang/NNP Besok/NNP pagi/NN :/: :/: :/: Minggu/NNP。但如果代码满足 /:/IN 标记,我希望它停止。这是到目前为止的代码:

import re

def entityExtract(text):
    # text = re.findall(r'([^\s/]*/IN\b[^/]*(?:/(?!IN\b)[^/]*)*/NNP\b)', text)
    text = re.findall(r'([^\s/]*/IN\b[^/]*(?:/(?!IN\b)[^/]*)*/(?:NNP|CDP)\b)', text)
    return text

text = "Alun-alun/NNP Jombang/NNP tepatnya/RB Depan/IN SMP/NNP 2/CDP Jombang/NNP Besok/NNP pagi/NN :/: :/: :/: Minggu/NNP"

extract = entityExtract(text)

print text
print extract

输出:

['Depan/IN SMP/NNP 2/CDP Jombang/NNP Besok/NNP pagi/NN :/: :/: :/: Minggu/NNP']

预期结果是:

['Depan/IN SMP/NNP 2/CDP Jombang/NNP Besok/NNP]

最好的解决方法是什么?

[^\s/]*/IN\b([^/]*/(?!IN\b|:\b)[^\s^/]*\b)*[^/]*/NNP\b

我和@DYZ 一样对你想在哪里停下来感到困惑,所以我的正则表达式基于你的输出。
我相信您想提取字符串的 'word/tag' 部分并且 word+tag 是强耦合的。

你想在什么地方停止你的标签而不包括它是由这个组控制的(?!IN\b|:\b|NN\b)

检查正则表达式 here

我查看了@bulbus 的答案和@ytomo 在评论中显示的正则表达式,即:

[^\s/]*/IN\b[^/]*(?:/(?!IN\b|:\b)[^/]*\b)*/(?:NNP|CDP)\b

我的问题是,这个提案和其他提案没有遵循逻辑顺序来为手头的问题创建正则表达式。让我告诉你:

第一部分,在我将简化为 \w+/IN\b[^/]*' 的重复组 [^\s/]*/IN\b[^/]* 之前,匹配的次数超出了您的预期。看看example 1.

你在这里解决的问题,换句话说,是:

  • 阅读一个 \w+/IN 组
  • 后跟任意数量的 \s[^/]+/\w+ 组,这不是 \w+/IN\b
  • 只要你能读.....直到
  • ..你已经匹配了你能找到的最后一个 NNP 或 CDP 组。

将其直接翻译成正则表达式,您将得到一个更具可读性的版本。 (JMHO)

  1. \w+/IN\b(\s[^/]+/[^\s]+) IN-group (example 2)
  2. 后阅读第一组
  3. \w+/IN\b(\s[^/]+/[^\s]+)* 重复第二组 (example 3)
  4. \w+/IN\b(\s[^:/]+/(?!IN|:)[^\s]+)* 忽略 :/: 和 \w+/IN 组 (example 4)
  5. \w+/IN\b(\s[^:/]+/(?!IN|:)[^\s]+)*\s\w+/(NNP|CDP)\b 确保你的最后一组是 NNP 或 CDP (example 5)

如果我们将此与前面答案的评论中@ytomo 的建议结果进行比较,似乎没有太大区别。然而,我什至懒得回答的原因是,正则表达式应该是可读的并且符合某种逻辑。您的代码明天将投入生产,并且 - 当您的代码出现问题时 - 必须有人在一定的时间压力下检查它。