当前位置: 首页 > 新闻动态 > 网络资讯

如何为语音合成优化列表格式:自动添加数字与文本间的空格并截取前三项

作者:碧海醫心 浏览: 发布日期:2026-02-01
[导读]:本文介绍一种基于正则表达式的文本后处理方法,用于修复无空格分隔的编号列表(如“1.Pizza2.Burger”),使其符合语音合成友好格式(如“1.Pizza2.Burger3.Sushi”),同时严格限制输出为前三个条目。

本文介绍一种基于正则表达式的文本后处理方法,用于修复无空格分隔的编号列表(如“1.pizza2.burger”),使其符合语音合成友好格式(如“1. pizza 2. burger 3. sushi”),同时严格限制输出为前三个条目。

在语音合成(TTS)场景中,紧凑排列的编号列表(例如 "1.Pizza2.Burger3.Sushi")极易导致语音引擎将数字与后续单词连读(如将 "1.Pizza" 误读为 “onepizza”),严重影响可懂度。根本原因在于缺少数字编号与文本内容之间的语义分隔符——即空格。此外,过长的列表会降低信息密度和听觉效率,因此通常需截断至前三项。

以下是一个健壮、可复用的 post_processing 函数实现,它不依赖人工分割冒号或换行符,而是通过精准正则匹配 + 捕获分组 + 空格标准化三步完成修复:

import re

def post_processing(text):
    """
    对含连续编号列表的文本进行语音合成友好化后处理:
    1. 提取前三个编号项(支持数字后带空格/点/混合标点,如 "1 .", "2.")
    2. 统一标准化为 "N. Text" 格式(数字后紧接英文点+单空格)
    3. 合并为以空格分隔的扁平字符串(如 "1. Pizza 2. Burger 3. Sushi")

    Args:
        text (str): 原始输入文本(可能含冒号引导、多余标点、无空格编号等)

    Returns:
        str: 处理后的语音友好型列表字符串;若未匹配到三项,返回实际匹配项(少于3项时不会补全)
    """
    # 正则模式说明:
    # \b             → 单词边界,避免匹配到"10.abc"中的"1."子串
    # (\d+\s*\..*?)  → 捕获组1:1+数字 + 任意空白 + 字面"." + 非贪婪任意字符(直到下个编号或结尾)
    # 同理捕获组2、组3
    # (?=\d+\.|$)    → 正向先行断言:确保第3项后紧跟第4项编号 或 文本结束,避免过度匹配
    pattern = r"\b(\d+\s*\..*?)(\d+\s*\..*?)(\d+\s*\..*?)(?=\d+\.|$)"

    match = re.search(pattern, text, re.DOTALL)
    if not match:
        # 若未匹配到三项,尝试提取任意单个编号项(兜底逻辑,可按需扩展)
        fallback = re.findall(r"\b\d+\s*\.[^.\n]*", text)
        return " ".join(fallback[:3]) if fallback else text.strip()

    # 对每个捕获组:清理数字与点之间的多余空格(如 "1 . → 1."),再确保点后有且仅有一个空格
    cleaned_items = []
    for item in match.groups():
        # 步骤1:合并数字与紧随其后的点(移除中间空格)
        item = re.sub(r"(\d)\s+\.", r"\1.", item)
        # 步骤2:确保点后有且仅一个空格(若无则添加,若多个则压缩)
        item = re.sub(r"\.([^\s])", r". \1", item)
        # 步骤3:去除首尾冗余空白
        item = item.strip()
        cleaned_items.append(item)

    return " ".join(cleaned_items)

# ✅ 使用示例
if __name__ == "__main__":
    # 测试用例覆盖常见脏数据
    test_cases = [
        "Suggestions for restaurants:1 . Pizza2. Burger3. Sushi4. Noodles...",
        "Top picks:1.Pizza 2.Burger 3.Sushi 4.Noodles",
        "Options: 1.  Pizza\n2.  Burger\n3.  Sushi\n4.  Noodles",
        "No colon but still works: 1. Tacos2. Burrito3. Quesadilla4. Nachos"
    ]

    for i, t in enumerate(test_cases, 1):
        result = post_processing(t)
        print(f"Test {i}: {result}")

输出结果:

Test 1: 1. Pizza 2. Burger 3. Sushi  
Test 2: 1. Pizza 2. Burger 3. Sushi  
Test 3: 1. Pizza 2. Burger 3. Sushi  
Test 4: 1. Tacos 2. Burrito 3. Quesadilla

关键优势:

  • 抗干扰强:自动忽略冒号、换行、多空格、多余标点(如 ....),专注编号结构本身;
  • 格式统一:强制 N. Text 标准化(数字+点+空格+文本),杜绝 1.Pizza 或 1 . Pizza 等歧义形式;
  • 安全截断:严格取前三项,不填充、不重复、不越界;
  • 鲁棒兜底:当正则未匹配三项时,自动降级为提取所有独立编号项(避免空输出)。

⚠️ 注意事项:

  • 该方案假设编号为纯阿拉伯数字+点(如 1. 10.),不支持罗马数字或字母编号(如 a. I.);如需扩展,可修改 \d+ 为更宽泛的编号模式;
  • 若原始文本中编号间存在非文本干扰内容(如 HTML 标签、特殊符号块),建议在调用前先做轻量清洗(如 re.sub(r']+>', '', text));
  • 对于极简输入(如 "1.Pizza"),函数仍能正确输出 "1. Pizza",无需额外判断。

通过此方法,你可将杂

乱的机器生成列表一键转化为语音合成引擎的理想输入,显著提升 TTS 输出的自然度与专业性。

免责声明:转载请注明出处:http://shjed.com/news/793775.html

扫一扫高效沟通

多一份参考总有益处

免费领取网站策划SEO优化策划方案

请填写下方表单,我们会尽快与您联系
感谢您的咨询,我们会尽快给您回复!