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

时间:2017-09-08 22:31:05

标签: python regex text-extraction

我有一句话:

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]

解决问题的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

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

我对@DYZ感到困惑,关于你想要停止的地方,所以我的正则表达式基于你的输出。
我相信你想要提取字符串的'word/tag'部分,word+tag是强耦合的。

您希望在不包含标记的情况下停止标记的位置由此组(?!IN\b|:\b|NN\b)

控制

检查正则表达式here

答案 1 :(得分:1)

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

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

我的问题是,这个 - 以及其他提议 - 不遵循逻辑顺序来为手头的问题创建正则表达式。让我告诉你:

第一部分,在重复小组[^\s/]*/IN\b[^/]*之前,我将简化为\w+/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
  6. 如果我们在前面的答案的评论中将这个与@ytomo的提议结果进行比较,似乎没有太大的区别。然而,我甚至不愿回答的原因是,正则表达式应该是可读的并且根据某些逻辑。你的代码将在明天开始生产,并且 - 当你的代码中断时 - 有人必须在一段时间的压力下检查它。