【问题标题】:Regex splitting punctuation from a string正则表达式从字符串中拆分标点符号
【发布时间】:2018-01-29 21:56:44
【问题描述】:

我想使用带有正则表达式(re.sub()re.findall())的空格来拆分 Python 字符串中的标点符号。所以"I like dog, and I like cat."应该变成"I like dog , and I like cat . "

我有一串标点符号 (python string.punctuation = "!"#$%&'()*+,-./:;<=>?@[\]^_{|}~") 我想替换,但我也有一个我不想替换的特定缩写列表(比如 list1 = ["e.g." , "Miss."]。我不想替换多个标点符号(任何两个相邻的标点符号,例如 ...,")或任何撇号,例如 I'm, you're, he's, we're

假设我有list1 = ["e.g." , "Miss."]string.punctuation = "!"#$%&'()*+,-./:;<=>?@[\]^_{|}~"。给定一个字符串"I'm a cat, you're a dog, e.g. a cat... really?, non-dog!!",它应该变成"I'm a cat , you're a dog , e.g. a cat ... really ?, non-dog !! "

除了我的特定缩写和多个标点符号和撇号列表之外,是否有正则表达式可以从字符串中拆分标点符号?

【问题讨论】:

  • 你为什么要这样做?
  • 提供更可测试的扩展输入字符串,涵盖所有条件。然后,发布预期的结果
  • 为了分类目的对文本正文进行预处理。
  • 为什么使用单个正则表达式可以通过一些代码更轻松、更灵活地完成?我想象一个正则表达式添加 all 空格,然后处理异常列表。这几乎是规范的“让我们使用正则表达式 - 然后你有 两个 问题”。
  • 有一些代码也很好,我只是想找到一个解决方案,我一直在使用正则表达式并卡住了。你有一些我可以遵循的示例代码吗?

标签: python regex string nlp


【解决方案1】:

一般算法是从头到尾处理输入字符串,扫描下一个“单词”是否在例外列表中(如果是,则跳过它)或者是标点符号(如果是,则在周围添加空格)。

这导致了以下函数:

def preprocess(string, punctuation, exceptions):
    result = ''
    i = 0
    while i < len(string):
        foundException = False
        if i == 0 or not(string[i-1].isalpha()):
            for e in exceptions:
                if string[i:].lower().startswith(e.lower()) and (i+len(e) == len(string) or not(string[i+len(e)].isalpha())):
                    result += string[i:i+len(e)]
                    i += len(e)
                    foundException = True
                    break
        if not(foundException):
            if string[i] in punctuation:
                result += ' '
                while i < len(string) and string[i] in punctuation:
                    result += string[i]
                    i += 1
                result += ' '
            else:
                result += string[i]
                i += 1

    return result.replace('  ', ' ')

在测试框架中运行时

examples = """
I like dog, and I like cat.
I'm a cat, you're a dog, e.g. a cat... really?, non-dog!!
"""

for line in examples.split('\n'):
    result = preprocess (line, "!\"#$%&'()*+,\\-./:;<=>?@[\]^_{|}~", ["I'm", "you're", "e.g.", "he's", "we're", "Miss."])
    print (result)

你得到第一句话的预期结果

I like dog , and I like cat .

但第二句话分裂了non-dog

I'm a cat , you're a dog , e.g. a cat ... really ?, non - dog !! 

这表明您的规范不准确(除非 non-dog 出现在例外列表中;然后它的行为符合预期)。

【讨论】:

  • 谢谢!这行得通。但有一件事是我意识到您的解决方案仅适用于e.g. 之类的缩写,但不适用于Mr. 之类的缩写,即使我将Mr. 放在我的例外列表中,它仍然不起作用。即Mr. 仍然被分隔为Mr . 。你有什么建议可以快速解决这个问题吗?
  • @Davvvvad:你说得对,听起来好像应该奏效了。我去看看。
  • @Davvvvad:我刚刚将"Mr." 添加到例外列表中,它按预期工作。没有其他变化;我复制了我的确切代码。 "Mr. I like dog, Mr. and I like Mr." 处理到预期的Mr. I like dog , Mr. and I like Mr.
  • 你说得对,我对你的代码做了修改。我的错。非常感谢!
【解决方案2】:

我会使用像[\.\,\:\;\?\(\)] 这样的正则表达式模式来查找字符串中所有标点符号的匹配列表。然后循环每个匹配项,将其替换为自身并附加一个空格。

例子:

data = "this is, the data."

myre = re.compile(r"[\.\,\:\;\?\(\)]")
matches = myre.findall(data)

for (var i = 0; i < matches.length; i++) {

    data.replace(matches[i], " "+matches[i])

}

【讨论】:

  • 是的,但这并不能解决我不想替换的某些特定模式的问题。
  • @Davvvvad 你能不能只用你想搜索的标点符号动态构建正则表达式?
猜你喜欢
  • 2013-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多