Jelle
Jelle

Reputation: 298

Regex for comma separated string

I'm not a regex-master, but I'm looking for a regex that would give this result in js:

var regex = ...;
var result = '"a b", "c, d", e f, g, "h"'.match(regex);

and result would be

['"a b"', '"c, d"', 'e f', 'g', '"h"']

EDIT:

Escaped quotes don't need to be handled. It's for a tagging field, where users must be able to enter:

tag1, tag2

but also

"New York, USA", "Boston, USA"

EDIT2: Thank you for your amazingly quick answer minitech, that did the trick!

Upvotes: 0

Views: 189

Answers (3)

Ωmega
Ωmega

Reputation: 43703

var result = input.match(/(?:(?:"((?:[^"]|"")*)")|([^",\n]*))/g);
for (var i = 0; i < result.length; i++) {
  result[i] = result[i].replace(/^\s*/, "").replace(/\s*$/, "");
  if (result[i].length === 0) {
    result.splice(i--, 1);
  }
}

Test this code here.

Upvotes: 0

icktoofay
icktoofay

Reputation: 129139

Regular expressions may not be the best tool for this task. You may want to instead do it instead by looping through the characters and deciding what to do. Here's some pseudocode that would do that:

  • Loop through the characters:
    • Is it a quote?
      • Toggle the quote flag.
    • Is it a comma when the quote flag is not set?
      • Add the accumulated string to the array.
      • Clear the accumulated string.
      • Skip the remaining steps in this iteration.
    • Add the current character to the string being accumulated.
  • Is the accumulated string not empty?
    • Add the accumulated string into the array.
  • Optionally, strip the whitespace off of all the strings in the array.
    This could also be done when adding the strings into the array.

Upvotes: 1

Ry-
Ry-

Reputation: 225269

I'd just use a loop:

function splitCSVFields(row) {
    var result = [];
    var i, c, q = false;
    var current = '';

    for(i = 0; c = row.charAt(i); i++) {
        if(c === '"') {
            current += c;
            q = !q;
        } else if(c === ',' && !q) {
            result.push(current.trim());
            current = '';
        } else {
            current += c;
        }
    }

    if(row.length > 0) {
        result.push(current.trim());
    }

    return result;
}

Note: requires String#trim, which you can shiv as follows:

if(!String.prototype.trim) {
    String.prototype.trim = function() {
        return this.replace(/^\s+/, '').replace(/\s+$/, '');
    };
}

Upvotes: 3

Related Questions