如何让JavaScript的.split()方法将带引号的多流派视为单个元素?
滚石Top500专辑分类项目:解决CSV带引号字段的分割问题
问题场景
我正在做一个将滚石杂志Top 500专辑按流派分类的项目,用.split(',')分割CSV格式的专辑数据时遇到了问题:部分专辑的流派是用引号包裹的多流派(比如"Rock, Pop"),直接按逗号分割会把这个字段拆成两个元素,导致数据结构混乱。
示例CSV数据
Rank, Year, Album, Band, "Genre1, Genre2", Sub-genre 5,1965,Rubber Soul,The Beatles,"Rock, Pop",Pop Rock
需求
实现分割逻辑,跳过引号内的逗号,确保整个流派部分作为数组的单个元素(数组索引0=排名,1=年份,2=专辑名,3=乐队,4=流派),且不能使用jQuery,基于现有的FileReader代码框架修改。
现有代码框架
let fichierAlbums = document.getElementById("input-fichier"); function lireFichier() { let reader = new FileReader(); // 获取第一个文件,加载完成后调用lireInfo() reader.readAsText(fichierAlbums.files[0]); reader.onload = lireInfo; } function lireInfo() { // 文件文本内容 let fichierAlbums = this.result; let lignesAlbums = fichierAlbums.split("\n"); for (let ligneIndex = 0; ligneIndex < lignesAlbums.length; ligneIndex++) { let ligneAlbumsTrimmed = lignesAlbums[ligneIndex].trim(); console.log(ligneAlbumsTrimmed); // 此处需要替换分割逻辑 } }
解决方案
方案1:正则表达式分割(简洁高效)
用正则匹配CSV字段,自动识别带引号的内容,跳过引号内的逗号。修改lireInfo函数如下:
function lireInfo() { // 文件文本内容 let fichierAlbums = this.result; let lignesAlbums = fichierAlbums.split("\n"); for (let ligneIndex = 0; ligneIndex < lignesAlbums.length; ligneIndex++) { let ligneAlbumsTrimmed = lignesAlbums[ligneIndex].trim(); if (!ligneAlbumsTrimmed) continue; // 跳过空行 // 匹配带引号或不带引号的CSV字段 const regex = /(".*?"|[^",]+)(?=\s*,|\s*$)/g; let champs = ligneAlbumsTrimmed.match(regex); // 清理字段:去除引号和多余空格 champs = champs.map(champ => { champ = champ.trim(); if (champ.startsWith('"') && champ.endsWith('"')) { return champ.slice(1, -1).trim(); } return champ; }); console.log(champs); // 输出示例:["5", "1965", "Rubber Soul", "The Beatles", "Rock, Pop", "Pop Rock"] } }
方案2:手动逐字符解析(适合理解原理)
如果正则不好理解,可以手动遍历字符,标记是否处于引号内,决定是否分割:
function lireInfo() { // 文件文本内容 let fichierAlbums = this.result; let lignesAlbums = fichierAlbums.split("\n"); for (let ligneIndex = 0; ligneIndex < lignesAlbums.length; ligneIndex++) { let ligneAlbumsTrimmed = lignesAlbums[ligneIndex].trim(); if (!ligneAlbumsTrimmed) continue; // 跳过空行 let champs = []; let currentChamp = ''; let dansGuillemets = false; // 标记是否在引号内 for (let char of ligneAlbumsTrimmed) { if (char === '"') { dansGuillemets = !dansGuillemets; // 切换引号状态 continue; } if (char === ',' && !dansGuillemets) { // 遇到逗号且不在引号内,分割字段 champs.push(currentChamp.trim()); currentChamp = ''; } else { currentChamp += char; } } // 添加最后一个字段 champs.push(currentChamp.trim()); console.log(champs); // 输出结果和正则方案一致 } }
内容的提问来源于stack exchange,提问作者rootbeer2017
相关产品推荐
相关产品推荐

