Reputation: 352
I tried now for three hours to construct the following regex match without much success. I have the following two strings:
This is a test string to illustrate the problem (example) in complex matching logic (Work / not working (in this case) to match this last occurring bracket closure)
and
Simpler version of the string (Matchable in any easy way)
I would like to define a str.match()
that matches this last part of the strings above. Resulting in:
Work / not working (in this case) to match this last occurring bracket closure
and
Matchable in any easy way
Any good way to achieve this? Sadly the data is highly volatile that a strong Regex is much rather preferred instead of long functional logic. Thanks so much!
Upvotes: 3
Views: 704
Reputation: 14361
RegEx is really impractical for this. Your regex would have to be extremely long, and will always have it's limitations. I really recommend using some parser. I like to use balanced.js.
var lastItem = balanced.matches({
source: string,
open: '(',
close: ')'
}).map(function (match) {
return string.substr(match.index + match.head.length, match.length - match.head.length - match.tail.length);
}).filter(function (a, b, c) {
return b === c.length - 1;
})[0] || "";
Results:
Simpler version of the string (Matchable in any easy way)
Matchable in any easy way
Upvotes: 1
Reputation: 224984
You can’t match arbitrarily deeply nested parentheses with regular expressions. Some regular expression engines have been extended in such a way that they can parse that kind of grammar, but JavaScript’s has not; you’ll need to match manually.
function lastParenthesizedSubstring(text) {
var end = text.lastIndexOf(')');
var i = end - 1;
var nesting = 1;
while (nesting > 0) {
if (i < 0) {
// Parenthesis imbalance! You may want to throw
// an exception or something.
return null;
}
var c = text.charAt(i);
if (c === ')') {
nesting++;
} else if (c === '(') {
nesting--;
}
i--;
}
return text.substring(i + 2, end);
}
Upvotes: 4
Reputation: 14361
Couldn't think of anything better. This also isn't 100% RegEx. Assume string
is your string
var matches = string.match(/(\([^(]*\))/g),
result = matches[matches.length-1].substring(0, matches[matches.length-1].length - 1);
Limitations
Upvotes: -1