¡Expresiones regulares al rescate! Estas pocas líneas de código manejan los campos entrecomillados correctamente con comas, comillas y nuevas líneas incrustadas según el estándar RFC 4180.
function parseCsv(data, fieldSep, newLine) {
fieldSep = fieldSep || ',';
newLine = newLine || 'n';
var nSep = 'x1D';
var qSep = 'x1E';
var cSep = 'x1F';
var nSepRe = new RegExp(nSep, 'g');
var qSepRe = new RegExp(qSep, 'g');
var cSepRe = new RegExp(cSep, 'g');
var fieldRe = new RegExp('(?<=(^|[' + fieldSep + '\n]))"(|[\s\S]+?(?<![^"]"))"(?=($|[' + fieldSep + '\n]))', 'g');
var grid = [];
data.replace(/r/g, '').replace(/n+$/, '').replace(fieldRe, function(match, p1, p2) {
return p2.replace(/n/g, nSep).replace(/""/g, qSep).replace(/,/g, cSep);
}).split(/n/).forEach(function(line) {
var row = line.split(fieldSep).map(function(cell) {
return cell.replace(nSepRe, newLine).replace(qSepRe, '"').replace(cSepRe, ',');
});
grid.push(row);
});
return grid;
}
const csv = 'A1,B1,C1n"A ""2""","B, 2","Cn2"';
const separator=","; // field separator, default: ','
const newline=" <br /> "; // newline representation in case a field contains newlines, default: 'n'
var grid = parseCsv(csv, separator, newline);
// expected: [ [ 'A1', 'B1', 'C1' ], [ 'A "2"', 'B, 2', 'C <br /> 2' ] ]
No necesita un generador de analizador sintáctico como lex / yacc. La expresión regular maneja RFC 4180 correctamente gracias a la búsqueda hacia atrás positiva, la búsqueda hacia atrás negativa y la búsqueda hacia adelante positiva.
Clonar / descargar código en https://github.com/peterthoeny/parse-csv-js