bflemi3
bflemi3

Reputation: 6790

Regex matching comma delimited strings

Given any of the following strings, where operator and value are just placeholders:

"operator1(value)"
"operator1(value), operator2(value)"
"operator1(value), operator2(value), operator_n(value)"

I need to be able to match so i can get each operator and it's value as follows:

[[operator1, value]]
[[operator1, value], [operator2, value]]
[[operator1, value], [operator2, value], [operator_n, value]]

Please Note: There could be n number of operators (comma delimited) in the given string.

My current attempt will match on operator1(value) but nothing with multiple operators. See regex101 for the results.

/^(.*?)\((.*)\)$/

Upvotes: 1

Views: 298

Answers (5)

Teemu
Teemu

Reputation: 23406

This can also be done with a simple split and a for loop.

var data = "operator1(value), operator2(value), operator_n(value)",
    ops = data.substring(0, data.length - 1), // Remove the last parenth from the string
    arr = ops.split(/\(|\), /),
    res = [], n, eN = arr.length;
for (n = 0; n < eN; n += 2) {
    res.push([arr[n], arr[n + 1]]);
}
console.log(res);

The code creates a flattened array from a string, and then nests arrays of "operator"/"value" pairs to the result array. Works for older browsers too.

Upvotes: 0

Bamieh
Bamieh

Reputation: 10906

The following function "check" will achieve what you are looking for, if you want a string instead of an array of result, simply use the .toString() method on the array returned from the function.

function check(str) {
  var myRe = /([^(,\s]*)\(([^)]*)\)/g;
  var myArray;
  var result = [];
  while ((myArray = myRe.exec(str)) !== null) {
    result.push(`[${myArray[1]}, ${myArray[2]}]`);
  };
  return result;
}

var check1 = check("operator1(value)");
console.log("check1", check1);

var check2 = check("operator1(value), operator2(value)");
console.log("check2", check2);

var check3 = check("operator1(value), operator2(value), operator_n(value)");
console.log("check3", check3);

Upvotes: 0

A_Elric
A_Elric

Reputation: 3568

Here's a pure regex answer to this question, this will work so long as your variables are always separated by a , and a space, should traverse through lines without much issue

https://regex101.com/r/eC3uK3/4

([^\(]*)(\([^, ]*\))(?:, )?(?:\n)?

Matches on: 

operator1(value), operator2(value), operator_n(value), 
operator1(value), operator2(value)

Explanation:

So, this sets up 2 capture groups and 2 non-capture groups.

The first capture group will match a value name until a parenthesis (by using a negated set and greedy). The second capture group will grab the parenthesis and the value name until the end of the parenthesis are found (note you can get rid of the parenthesis by escaping the outer set of parenthesis rather than the inner (Example here: https://regex101.com/r/eC3uK3/6). There's an optional ", " in a non capturing group, and an optional "\n" in another non-capturing group to handle any newline characters that you may happen across.

This should break your data out into:

'Operator1'
'(value)'
'operator2'
'(value)'

For as many as there are.

Upvotes: 1

chimericdream
chimericdream

Reputation: 432

You should be able to do this with a single regex using the global flag.

var re= /(?:,\s*)?([^(]+?)\(([^)]+)\)/g;
var results = re.exec(str);

See the result at Regex 101: https://regex101.com/r/eC3uK3/2

Upvotes: 1

Denys S&#233;guret
Denys S&#233;guret

Reputation: 382150

You can do this by first splitting then using a regular expression:

[
  "operator1(value)",
  "operator1(value), operator2(value)",
  "operator1(value), operator2(value), operator_n(value)"
].forEach((str)=>{
  var results = str
    .split(/[,\s]+/) // split operations
    .map(s=>s.match(/(\w+)\((\w+)\)/)) // extracts parts of the operations
    .filter(Boolean) // ensure there's no error (in case of impure entries)
    .map(s=>s.slice(1)); // make the desired result
  console.log(results);
});

Upvotes: 0

Related Questions