MarzSocks
MarzSocks

Reputation: 4318

Return text between brackets and not include brackets

I am using the following regEx to match text in brackets:

'textA(textB)'.match(/\((.+?)\)/g)

But it returns text including the brackets e.g. (textB)

How do I return the text without the brackets e.g. textB

Upvotes: 2

Views: 1411

Answers (4)

dogatonic
dogatonic

Reputation: 2788

Use the matchAll function instead. Maybe?

(your original regular expression was good enough for this)

for (const results of 'textA(textB)'.matchAll(/\((.+?)\)/g)) {
    console.log(results[0]) // outputs: (textB)
    console.log(results[1]) // outputs: textB
}

OR

const results = [...'textA(textB)(textC)'.matchAll(/\((.+?)\)/g)];
console.log(results) // outputs array of each result

The matchAll() method returns an iterator of all results matching a string against a regular expression, including capturing groups; index 0 returns the whole, and indexes after return group parts.

Upvotes: 0

nhahtdh
nhahtdh

Reputation: 56809

It is possible to define a function which matches a string against a regex and customize the output array via a user-defined function.

String.prototype.matchf = function (re, fun) {
    if (re == null || re.constructor != RegExp) {
        re = new RegExp(re);
    }

    // Use default behavior of String.prototype.match for non-global regex.
    if (!re.global) {
        return this.match(re);
    }

    if (fun == null) { // null or undefined
        fun = function (a) { return a[0]; };
    }

    if (typeof fun != "function") {
        throw TypeError(fun + " is not a function");
    }

    // Reset lastIndex
    re.lastIndex = 0;
    var a;
    var o = [];

    while ((a = re.exec(this)) != null) {
        o = o.concat(fun(a));
    }

    if (o.length == 0) {
        o = null;
    }

    return o;
}

The user-defined function is supplied with an array, which is the return value of RegExp.exec.

The user-defined function is expected to return a value or an array of values. It can return an empty array to exclude the content of the current match from the resulting array.

The behavior of the custom function above should be the same as String.match when user-defined function fun is not supplied. This should have less overhead compared to abusing String.replace to extract an array, since it doesn't have to construct the replaced string.

Back to your problem, using the custom function above, you can write your code as:

'textA(textB)'.matchf(/\((.+?)\)/g, function (a) {return a[1];});

Upvotes: 0

Pointy
Pointy

Reputation: 413702

You have to explicitly include the parentheses in the regular expression by quoting them with \

'textA(textB)'.match(/\((.+?)\)/g)

If you don't do that, the outer parentheses are interpreted as regex metacharacters.

To extract the matched text without the surrounding parentheses:

var match = 'textA(textB)'.match(/\((.+?)\)/); // no "g"
var text = match[1];

It's tricky to create a regular expression that works with the "g" ("global") qualifier to match and collect the strings within parentheses, because that qualifier causes the .match() function return value to change. Without "g", the .match() function returns an array with the overall match in position 0 and the matched groups in subsequent positions. However, with the "g", .match() simply returns all matches of the entire expression.

The only way I can think of is to repeatedly match, and the easiest way to do that (in my opinion) is with a function:

var parenthesized = [];
var text = "textA (textB) something (textC) textD) hello (last text) bye";
text.replace(/\((.+?)\)/g, function(_, contents) {
    parenthesized.push(contents);
});

That will accumulate the properly-parenthesized strings "textB", "textC", and "last text" in the array. It will not include "textD" because it is not properly parenthesized.

Upvotes: 0

Avinash Raj
Avinash Raj

Reputation: 174696

I assume that the input contains balanced parenthesis. If yes, then you could use the below regex to match all characters which are present within the brackets.

[^()]+(?=\))

DEMO

> 'textA(textB)'.match(/[^()]+(?=\))/g)
[ 'textB' ]

Explanation:

  • [^()]+ Negated character class which matches any character but not of ( or ) one or more times.
  • (?=\)) positive lookahead which asserts that the matched characters must be followed by a closing parenthesis )

Upvotes: 2

Related Questions