You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从散文中拆分句子:保留对话标记与标点的技术难题

解决散文句子拆分并保留对话标记的问题

我来帮你搞定这个句子拆分的问题!针对你提到的两个核心痛点——区分Mr.这类缩写的句点和句末标点、正确保留对话引号,我整理了一套可行的实操方案:

一、先搞定缩写句点的误判问题

首先,我们得给常见的英文缩写建个「白名单」,比如Mr.、Mrs.、Dr.、St.这些,避免拆分时把它们的句点当成句子结束的标志。具体步骤是:

  • 先遍历文本,把缩写里的句点替换成一个临时占位符(比如__DOT__),这样后续拆分句子时就不会认错。
  • 等句子拆分完成后,再把占位符还原回正常的句点。

二、正确处理对话引号的拆分逻辑

对话的引号必须和对应的句子绑定,不能拆分家。这里的关键是先把对话和非对话内容分开处理:

  1. 分割对话与非对话:通过匹配成对的引号(“和”)把文本拆成对话片段和非对话片段。
  2. 拆分对话内部的句子:在对话片段里,以!、?、.(已经处理过缩写的句点)作为句子结束的标志拆分。
  3. 给对话句子补全引号:每个拆分后的对话句子,都要加上首尾的引号,保证格式完整。
  4. 非对话部分正常拆分:直接按句末标点拆分就行,不用管引号。

三、示例实现(伪代码)

下面是用Python写的核心逻辑,你可以直接参考调整:

# 第一步:定义缩写白名单
abbreviation_list = {"Mr.", "Mrs.", "Dr.", "St.", "Jr.", "Sr."}

def mark_abbreviations(text):
    # 把缩写里的句点换成占位符
    for abbr in abbreviation_list:
        text = text.replace(abbr, abbr.replace(".", "__DOT__"))
    return text

def restore_abbreviations(text):
    # 把占位符还原回句点
    return text.replace("__DOT__", ".")

def split_dialogue_sections(text):
    # 拆分对话和非对话片段
    sections = []
    current_index = 0
    while True:
        # 找对话起始引号
        start_quote = text.find("“", current_index)
        if start_quote == -1:
            # 剩下的都是非对话内容
            if current_index < len(text):
                sections.append(("non_dialogue", text[current_index:].strip()))
            break
        # 提取引号前的非对话内容
        if start_quote > current_index:
            sections.append(("non_dialogue", text[current_index:start_quote].strip()))
        # 找对话结束引号
        end_quote = text.find("”", start_quote + 1)
        if end_quote == -1:
            # 处理不完整的引号(可选逻辑)
            sections.append(("dialogue", text[start_quote:].strip()))
            break
        # 提取对话内容(去掉首尾引号)
        dialogue_content = text[start_quote+1:end_quote].strip()
        sections.append(("dialogue", dialogue_content))
        current_index = end_quote + 1
    return sections

def split_into_sentences(text):
    # 按句末标点拆分句子
    sentence_endings = {"!", "?", "."}
    sentences = []
    current_sentence = ""
    for char in text:
        current_sentence += char
        if char in sentence_endings:
            sentences.append(current_sentence.strip())
            current_sentence = ""
    # 处理最后一段没写完的句子
    if current_sentence.strip():
        sentences.append(current_sentence.strip())
    return sentences

def split_text_with_dialogue(text):
    # 主函数:整合所有逻辑
    # 1. 标记缩写
    processed_text = mark_abbreviations(text)
    # 2. 拆分对话和非对话
    sections = split_dialogue_sections(processed_text)
    final_result = []
    for section_type, content in sections:
        if section_type == "dialogue":
            # 拆分对话句子,补全引号
            dialogue_sentences = split_into_sentences(content)
            for sent in dialogue_sentences:
                restored_sent = restore_abbreviations(sent)
                final_result.append(f“{restored_sent}”)
        else:
            # 拆分非对话句子
            non_dialogue_sentences = split_into_sentences(content)
            for sent in non_dialogue_sentences:
                restored_sent = restore_abbreviations(sent)
                final_result.append(restored_sent)
    return final_result

# 测试你的示例文本
test_input = "“Dirty, Mr. Jones? Look at my shoes! Not a speck on them.” This is a non-dialogue sentence!"
print(split_text_with_dialogue(test_input))
# 输出:["“Dirty, Mr. Jones?”", "“Look at my shoes!”", "“Not a speck on them.”", "This is a non-dialogue sentence!"]

四、一些额外提示

  • 缩写白名单可以根据你的需求扩展,比如加入行业专属的缩写(像Prof.、Cmdr.这类)。
  • 如果你的文本用的是英文引号("),只需要把代码里的“和”换成"就行。
  • 要是遇到嵌套对话(比如对话里又引用了别人的话),可能需要加递归处理逻辑,但基础场景下上面的代码已经完全够用了。

内容的提问来源于stack exchange,提问作者Kevin Connors

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:49:53