【发布时间】:2014-09-23 16:44:09
【问题描述】:
我有一个需要解析的 CSV 文件类型。以下正是我需要考虑的条件(缺少列标题、引号内的换行符、缺少数据等):
ID,NAME,TITLE,DESCRIPTION,,
PRO1234,"JOHN SMITH",ENGINEER,"JOHN HAS BEEN WORKING
HARD ON BEING A GOOD
SERVENT."
PRO1235,"KEITH SMITH",ENGINEER,"keith has been working
hard on being a good
servent."
PRO1235,"KENNY SMITH",,"keith has been working
hard on being a good
servent."
PRO1235,"RICK SMITH",,,
您会注意到说明中有换行符以及新数据行的换行符。
我编写了这个正则表达式来查找引号之外的换行符,它非常有效here
代码,使用 Node.js:
var fs = require('fs');
function parseCSV(filename){
var rx = new RegExp(/\n(?=([^"\\]*(\\.|"([^"\\]*\\.)*[^"\\]*"))*[^"]*$)/g);
var strFile = fs.readFileSync(filename).toString();
console.log("line feed count via match: " + strFile.match(rx).length);
var csv = strFile.split(rx);
console.log("csv length: " + csv.length);
console.log("csv items ###############################");
csv.forEach(function(e,i,a){
console.log("item e: " + e);
});
}
当我运行此程序时,您会看到换行数(通过匹配找到的换行)是正确的,即 4。然而,当使用 String.split() 相同的 ret 时,它返回 17 并且结果数组是不稳定的:
line feed count via match: 4
csv length: 17
csv items ###############################
item e: ID,NAME,TITLE,DESCRIPTION,,
item e:
PRO1235,"RICK SMITH"
item e: "RICK SMITH"
item e: undefined
item e: PRO1234,"JOHN SMITH",ENGINEER,"JOHN HAS BEEN WORKING
HARD ON BEING A GOOD
SERVENT."
item e:
PRO1235,"RICK SMITH"
item e: "RICK SMITH"
item e: undefined
item e: PRO1235,"KEITH SMITH",ENGINEER,"keith has been working
hard on being a good
servent."
item e:
PRO1235,"RICK SMITH"
item e: "RICK SMITH"
item e: undefined
item e: PRO1235,"KENNY SMITH",,"keith has been working
hard on being a good
servent."
item e: PRO1235,"RICK SMITH"
item e: "RICK SMITH"
item e: undefined
item e: PRO1235,"RICK SMITH",,,
我在拆分时做错了什么?我的想法是,如果我可以识别 4 个与 match() 完美配合的换行符,那么同一个正则表达式应该提供“拆分”字符串的位置。
【问题讨论】:
-
重新发明轮子的经典案例。 Why not use a dedicated CSV parser for this?
-
首先你不能从它们中间开始解析字符串。
-
sln - 你能解释一下你的评论吗?如果我正在调用 string.split(regExp),我如何解析中间的字符串?
-
您是否尝试解析 csv 文件?如果是这样,这个正则表达式将在有/没有你的换行问题的情况下处理它。
/(?:(?:^|,|\r?\n)\s*)(?:"([^"\\]*(?:\\[\S\s][^"\\]*)*)"(?:\s*(?:(?=,|\r?\n)|$))|([^,]*)(?:\s*(?:(?=,)|$)))/字段值为$1$2
标签: javascript regex string split match