如何用“。”分解句子,但忽略双引号中的“。”

时间:2013-12-28 14:52:49

标签: python regex python-3.x

我正在编写一个关于获取中文文章摘要的程序。首先,我必须用“。!?”之类的符号来爆炸每个句子。 在中文文章中,当引用其他词时,他们会使用双引号来标记所引用的词,这些词可能包含“。”但不应该分解。例如,以下句子:

他说:“今天天气很好我很开心”

它将分为三个句子:

  1. 他说:“今天天气很好
  2. 我很开心
  3. 结果是错误的,但如何解决呢? 我试过使用正则表达式,但我不擅长它,所以可以搞清楚。 PS:我用python3编写这个程序

5 个答案:

答案 0 :(得分:2)

我使用re.findall匹配所有句子而不是拆分:

>>> s = '今天天气很好。今天天气很好。今天天气很好。他说:“今天天气很好。我很开心。”'
>>> re.findall('[^。“]+(?:。|“.*?”)', s)
['今天天气很好。', '今天天气很好。', '今天天气很好。', '他说:“今天天气很好。我很开心。”']

如果您也想接受其他角色作为分隔符,请尝试以下方法:

>>> re.findall('[^。?!;~“]+(?:[。?!;~]|“.*?”)', s)

答案 1 :(得分:1)

首先,我假设双引号不能嵌套。然后在没有复杂的正则表达式的情况下很容易做到这一点。您只需在"上拆分,然后在标点符号上拆分偶数部分。

>>> sentence = 'a: "b. c" and d. But e said: "f? g."'
>>> sentence.split('"')
['a: ', 'b. c', ' and d. But e said: ', 'f? g.', '']

你可以看到偶数部分是如何不是引号之间的部分。我们将使用index % 2 == 1来选择奇数部分。

result = []
part = []
for i, p in enumerate(sentence.split('"')):
    if i % 2 == 1:
        part.append(p)
    else:
        parts = p.split('.')
        if len(parts) == 1:
            part.append(p)
        else:
            first, *rest, last = parts
            part.append(first)
            result.append('"'.join(part))
            result.extend(rest)
            part = [last]

result.append('"'.join(part))

答案 2 :(得分:1)

使用正则表达式:

import re

st=u'''\
今天天气很好。今天天气很好。bad? good! 今天天气很好。他说:“今天天气很好。我很开心。”
Sentence one. Sentence two! “Sentence three. Sentence four.” Sentence five?'''

pat=re.compile(r'(?:[^“。?!;~.]*?[?!。.;~])|(?:[^“。?!;~.]*?“[^”]*?”)')
print(pat.findall(st))

打印:

['今天天气很好。', '今天天气很好。', 'bad?', ' good!', ' 今天天气很好。', 
 '他说:“今天天气很好。我很开心。”', '\nSentence one.', ' Sentence two!', 
 ' “Sentence three. Sentence four.”', ' Sentence five?']

如果你想要分割效果(即不包括分隔符),只需移动捕获括号,然后打印匹配组:

pat=re.compile(r'([^“。?!;~.]*?)[?!。.;~]|([^“。?!;~.]*?“[^”]*?”)')
#  note the end paren:           ^
print([t[0] if t[0] else t[1] for t in pat.findall(st)])

打印:

['今天天气很好', '今天天气很好', 'bad', ' good', ' 今天天气很好', 
 '他说:“今天天气很好。我很开心。”', '\nSentence one', ' Sentence two', 
 ' “Sentence three. Sentence four.”', ' Sentence five']

或者,使用具有相同正则表达式的re.split,然后筛选True值:

print(list(filter(None, pat.split(st))))   

答案 3 :(得分:0)

我认为你需要分两步完成:首先,找到双引号内的点,并“保护”它们(例如,用$%$%$%$之类的字符串替换它们,这些字符串不太可能出现在中文文本。接下来,像以前一样爆炸字符串。最后,再次用点替换$%$%$%$

答案 4 :(得分:0)

可能会有效:

$str = '他说:“今天天气很好。我很开心。”';
print_r( preg_split('/(?=(([^"]*"){2})*[^"]*$)。/u', $str, -1, PREG_SPLIT_NO_EMPTY) );

这可确保仅在外部双引号时匹配。

<强>输出:

Array
(
    [0] => 他说:“今天天气很好
    [1] => 我很开心
    [2] => ”
)