0

0

JavaScript字符串解析:智能拆分单词并保留双引号短语

DDD

DDD

发布时间:2025-09-01 14:59:35

|

1044人浏览过

|

来源于php中文网

原创

JavaScript字符串解析:智能拆分单词并保留双引号短语

在JavaScript中,我们经常需要将文本字符串拆分成独立的词语或短语进行处理。然而,当字符串中包含用双引号括起来的多词短语时,简单的 split(' ') 方法往往无法满足需求,它会将短语内部的空格也作为分隔符,导致短语被错误地拆分。例如,将 "on time" "flight" 拆分为 ["on", "time", "flight"] 而非期望的 ["on time", "flight"]。为了解决这一挑战,我们需要一种更智能的解析策略,其中有限状态机(Finite-State Machine, FSM)是一种非常有效的方法。

核心概念:有限状态机(FSM)解析

有限状态机是一种数学模型,用于描述系统在不同状态之间转换的行为。在字符串解析的场景中,我们可以定义几个状态来表示解析器当前正在处理的文本类型:

  1. 初始/空闲状态 (Initial/Idle State): 解析器等待接收下一个字符,并根据字符类型决定进入何种工作模式。
  2. 单词模式 (Word Mode): 解析器正在累积一个普通的单词。
  3. 短语模式 (Phrase Mode): 解析器正在累积一个双引号内的短语。

通过在这些状态之间切换,并根据当前字符和当前状态执行不同的操作,我们可以精确地识别出独立的单词和完整的带引号短语。

实现细节与代码解析

下面我们将通过一个JavaScript函数 splitToWordsWithQuotes 来演示如何使用FSM思想实现字符串的智能分词。

function splitToWordsWithQuotes(str) {
    let mode; // 当前解析模式:'word' (普通单词) 或 'phrase' (引号内短语)
    const words = []; // 存储最终拆分出的单词和短语
    let word = ''; // 临时缓冲区,用于累积当前正在解析的单词或短语

    // 辅助函数:将当前累积的word添加到words数组中,并清空word缓冲区
    const completeWord = () => {
        if (word) { // 只有当word不为空时才添加
            words.push(word);
            word = '';
        }
    };

    for (let i = 0; i < str.length; i++) {
        const c = str[i]; // 当前字符

        // 状态一:初始/空闲状态,尚未确定解析模式
        if (!mode) {
            if (c === ' ') {
                continue; // 忽略开头的空格
            }
            if (c === '"') {
                mode = 'phrase'; // 遇到双引号,进入短语模式
            } else {
                word += c; // 遇到非空格非引号字符,开始累积单词
                mode = 'word'; // 进入单词模式
            }
            continue; // 处理下一个字符
        }

        // 状态二:已进入某种解析模式

        // 遇到双引号
        if (c === '"') {
            completeWord(); // 结束当前单词或短语的累积
            // 切换模式:如果当前是单词模式,遇到引号表示进入短语;反之,表示短语结束进入单词
            mode = mode === 'word' ? 'phrase' : 'word';
            continue; // 处理下一个字符
        }

        // 遇到空格
        if (c === ' ') {
            if (mode === 'phrase') {
                word += ' '; // 在短语模式下,空格是短语的一部分,累积到word中
                continue; // 处理下一个字符
            }
            // 在单词模式下,空格是分隔符
            completeWord(); // 结束当前单词的累积
            // 保持当前模式不变(或可以理解为回到空闲状态等待下一个非空格字符)
            continue; // 处理下一个字符
        }

        // 遇到其他字符(字母、数字等)
        word += c; // 累积到当前单词或短语中
    }

    // 循环结束后,确保将最后一个累积的word添加到words数组中
    completeWord();

    return words;
}

代码解析要点:

  • mode 变量: 这是FSM的核心,它跟踪解析器的当前状态('word' 或 'phrase')。
  • words 数组与 word 缓冲区: word 用于临时存储正在构建的词语或短语,当一个词语/短语完成时,通过 completeWord() 函数将其推入 words 数组。
  • completeWord() 辅助函数: 封装了将缓冲区内容添加到结果列表并清空缓冲区的逻辑,避免代码重复。
  • 字符遍历与状态判断:
    • 初始状态 (!mode): 负责跳过前导空格,并根据遇到的第一个非空格字符确定是进入 word 模式还是 phrase 模式。
    • 遇到双引号 (c === '"'): 这是一个关键的切换点。它总是表示当前词语/短语的结束,并切换解析模式。
    • 遇到空格 (c === ' '):
      • 在 phrase 模式下,空格被视为短语内容的一部分,直接累积。
      • 在 word 模式下,空格被视为分隔符,触发 completeWord()。
    • 遇到其他字符: 无论是 word 模式还是 phrase 模式,这些字符都被累积到 word 缓冲区中。
  • 循环结束后的处理: completeWord() 在循环结束后再次调用,确保字符串末尾的最后一个词语或短语也被正确收集。

示例与输出

让我们使用一些示例来验证这个解析器的功能:

Cursor
Cursor

一个新的IDE,使用AI来帮助您重构、理解、调试和编写代码。

下载

立即学习Java免费学习笔记(深入)”;

const myStr = '    "hello guys", some     words with "quotes inside"" some spaces inside " please keep quoted words as one "phrase / word" end-of-line ';
const mySimpleStr = '"on time" "flight"';

console.log('--- 复杂字符串示例 ---');
console.log('原始字符串:', myStr);
console.log('解析结果:', splitToWordsWithQuotes(myStr));
// 预期输出: ["hello guys", ",", "some", "words", "with", "quotes inside", "some", "spaces", "inside", "please", "keep", "quoted", "words", "as", "one", "phrase / word", "end-of-line"]

console.log('\n--- 简单字符串示例 ---');
console.log('原始字符串:', mySimpleStr);
console.log('解析结果:', splitToWordsWithQuotes(mySimpleStr));
// 预期输出: ["on time", "flight"]

如上所示,splitToWordsWithQuotes 函数能够正确处理前导/尾随空格、多个空格分隔符,以及最关键的——将双引号内的短语作为一个整体进行识别和提取。

注意事项与扩展思考

  1. 未闭合的引号: 当前的FSM实现对于未闭合的引号(例如 "hello world)不会抛出错误,而是会将其余部分当作一个普通单词处理。如果需要严格的引号匹配,可能需要引入额外的错误状态或在循环结束后检查 mode 是否仍为 'phrase'。
    const myWrongStr = '"hello guys", some words" with "quotes inside" please keep quoted words as one "phrase / word" ';
    console.log('\n--- 未闭合引号示例 ---');
    console.log('原始字符串:', myWrongStr);
    console.log('解析结果:', splitToWordsWithQuotes(myWrongStr));
    // 结果可能不是你想要的,例如 "words" 会被拆分成 "words" 而不是 "words"
    // 并且 "phrase / word" 后的引号没有关闭,会导致后续文本被错误解析
  2. 转义引号: 如果字符串中存在转义的引号(例如 \"),当前的解析器会将其视为普通字符。要支持转义引号,需要在遇到 \ 字符时增加额外的逻辑来处理。
  3. 性能: 对于极长的字符串,逐字符遍历的性能通常是可接受的。如果性能成为瓶颈,可以考虑使用更底层的语言特性或优化字符串操作。
  4. 后续处理: 本文的FSM主要解决了字符串的“拆分”问题。如果需要将拆分后的短语进一步格式化(例如,将 ["on time", "flight"] 转换为 ""ON TIME"FLIGHT"),则需要在此解析结果的基础上进行二次处理。例如:
    const tokens = splitToWordsWithQuotes('"on time" "flight"'); // ["on time", "flight"]
    const formattedOutput = tokens.map(token => {
        if (token.includes(' ')) { // 简单判断是否为多词短语
            return `"${token.toUpperCase()}"`;
        }
        return token.toUpperCase();
    }).join(''); // 假设需要连接成一个字符串
    console.log('\n--- 格式化示例 ---');
    console.log('格式化后的输出:', formattedOutput); // ""ON TIME"FLIGHT"

总结

通过采用有限状态机的方法,我们可以构建一个健壮的JavaScript字符串解析器,有效地解决在复杂文本中区分普通单词和带引号短语的挑战。这种方法不仅提供了精确的分词能力,也为处理更复杂的字符串解析需求(如支持转义字符、处理不同类型的引号等)奠定了基础。理解并应用FSM模式,能够显著提升我们处理字符串数据的能力和代码的专业性。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

761

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1570

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

651

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

1229

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

1205

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

193

2025.07.29

c++字符串相关教程
c++字符串相关教程

本专题整合了c++字符串相关教程,阅读专题下面的文章了解更多详细内容。

131

2025.08.07

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

49

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 6.1万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 3.4万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号