Parse a CSV row
Parse a CSV row according to the RFC 4180
by rplantiko
HTML
<h2>Other solutions out there?</h2>
Two possible functions to parse a CSV row as specified in <a href="https://tools.ietf.org/html/rfc4180">RFC 4180</a>
<p>
<b>Single row:</b>
<p>
<textarea id="input" cols="80" rows="3"></textarea>
</p>
<p>
<button type="button" id="parse">Parse</button>
</p>
<pre id="log"></pre>
JavaScript
"use strict";
var log = document.getElementById("log")
document.getElementById("input").value =
`1,a,"a","""Hallo"",he said, ""howdy?""","",,"Hi, there","""Hi, there""
""Oh, that was a line break"""`
document.getElementById("parse").addEventListener("click", function() {
var input = document.getElementById("input").value
log.textContent = input + "\n\n"
show( parseCSV1( input ) )
show( parseCSV2( input ) )
})
function show(result) {
log.insertAdjacentText("beforeend","\n")
result.forEach((cell,i)=>
log.insertAdjacentText("beforeend",`${i+1}: ${cell}\n`)
)
}
// Version 1: Scan through the string with for..of
function parseCSV1(row,sep=',') {
var result = []
var quoteMode = false, s = "", c
for (c of row) {
quoteMode = quoteMode != (c == '"')
if (!quoteMode && c == sep) {
addToResult(s)
s = ""
} else
s+=c
}
if (s || c == sep) addToResult(s)
return result
function addToResult(cell) {
result.push(
cell.replace(/(?!^)""/g,'"')
.replace(/^"([\s\S]*)"$/,"$1")
)
}
}
// Version 2: use Array function 'reduce()'
function parseCSV2(row,sep=',') {
var len = row.length,
quoteMode = false,
prev = 0
return (row+" ").split('').reduce(function(result,c,i) {
quoteMode = quoteMode != (c == '"')
if (!quoteMode && c == sep || i == len) {
result.push(
row.substring(prev,i)
.replace(/(?!^)""/g,'"')
.replace(/^"([\s\S]*)"$/,"$1")
)
prev = i+1
}
return result
},[])
}