简体   繁体   中英

How to get all values in parentheses in a string including nested parentheses?

Desired Behaviour

I have an input validation that, amongst other things, tests for length ( < 140 chars ).

My input accepts markdown, and I'd like to exclude the length of the URLs in my length calculation.

For example, something that appears as:

here is a very long link to this article on Math.random()

is 57 characters long, whereas the actual code for it is 155 characters long, ie:

here is a very long link to this article on [Math.random()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random)

The scenarios that need to be covered are things like:

text and [a markdown link](https://google.com)

text (and [a markdown link within parenthesis](https://google.com))

This question is about:

How to get all values in parentheses in a string including nested parentheses.

What I've Tried

My current approach to the overall problem is:

  1. get all values within parentheses in the string
  2. if any start with https , create a copy of the string
  3. remove the values from the copied string
  4. get the length of the adjusted string and run length validation on that

These are my attempts at the first part:

01)

This solution just gets the first "match", source: https://stackoverflow.com/a/12059321

 var text = "here is a (very) long link to this article on [Math.random()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random)"; var regExp = /\\(([^)]+)\\)/; var matches = regExp.exec(text); console.log(matches); // 0: "(very)" // 1: "very" 

02)

This solution gets all matches, with the parenthesis' included, source: https://stackoverflow.com/a/30674943

 var text = "here is a (very) long link to this article on [Math.random()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random)"; var regExp = /(?:\\()[^\\(\\)]*?(?:\\))/g; var matches = text.match(regExp); console.log(matches); // 0: "(very)" // 1: "()" // 2: "(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random)" 

But it doesn't work as expected in the nested parenthesis scenario, ie:

 var text = "text (and [a markdown link within parenthesis](https://google.com))"; var regExp = /(?:\\()[^\\(\\)]*?(?:\\))/g; var matches = text.match(regExp); console.log(matches); // ["(https://google.com)"] 

03)

There is a php regex solution here that seems to be related:

https://stackoverflow.com/a/12994041

but i couldn't figure out how to implement that regex in javascript, ie:

preg_match_all('/^\\((.*)\\)[ \\t]+\\((.*)\\)$/', $s, $matches);

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

Explanation:

(?<=\\() - assert with positive lookbehind that what preceds is (

[^()]+ - match one or more of any characters other than ( and )

(?=\\)) - assert with positive lookahead that what follows is )

Demo

I would use a regular expression that also requires the part in square brackets to precede the link that's within parentheses.

/\[([^\]]+)\]\([^)]+\)/g

Make sure to use the g flag. This also includes a capture group so you can differentiate the "visible" part (between square brackets) from the rest that is "invisible":

 var text = "here is a (very) long link to this article on [Math.random()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random)"; var regExp = /\\[([^\\]]+)\\]\\([^)]+\\)/g; var match; while (match = regExp.exec(text)) { console.log("full match: " + match[0]); console.log("keep: " + match[1]); } 

You can actually use a replace call to remove the "invisible" part. That makes it easy to calculate the total number of visible characters:

 var text = "here is a (very) long link to this article on [Math.random()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random)"; var regExp = /\\[([^\\]]+)\\]\\([^)]+\\)/g; console.log("original length: " + text.length); console.log("visible length: " + text.replace(regExp, "$1").length); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM