How to split a string with a comma in parentheses, but not a double quote
How can I grab the entire parameter in a sample string using Regex? I tried to use the (\ @ \ w + | \ w +) pattern at https://regex101.com/ , but it returns all words in the pattern string, which is not what I expect.
.selector(@background, height, font "font-family, font family", @width : 10px, "red");
expected output should capture 5 parameters:
1. @background
2. height
3. font "font-family, font family"
4. @width : 10px
5. "red"
I was having difficulty concatenating a regex and it took me an hour to figure it out, so I decided to ask for help.
source to share
First, I would extract the interesting part between the brackets, then I would read the internal parameters:
var args = str.match(/\(([^\)]+)\)/)[1].match(/[^,"]+("[^"]+")*/g)
Result:
The idea behind the second part ( [^,"]+("[^"]+")*
) is to explicitly include the parts between the quotes.
source to share
Here is the all-in-one regex:
/(?<=[,\(])(?:\s*)([^,"]*(?<dq>")?(?(dq)[^"]+"[^\(\),]*))(?:\s*)/g
Explanation:
- the parameter is either after the comma or with an open parenthesis -> manage this positive lookbehind
(?<=[,\(])
- but don't strip extra spaces ->
(?:\s*)
outside the caputring group (better). - In the capture group:
- start by matching anything other than a comma and a double quote.
- If a double quote is encountered, match it until another double quote is matched.
Have a look at https://regex101.com/r/pC9fB6/1 for results.
Note: dystroy points to the comment behind this lookbehind statement is not supported by all regex engines (like JavaScript). A possible solution is to place a class character [,\(]
lookbehind statements within the group, not exciting spaces: (?:[,\(]\s*)
. The result is almost the same, the numbered matches are the same.
source to share