...

View Full Version : Regex: Removing Nested Parentheses



neochronomo
07-23-2010, 10:18 AM
I simply cannot figure this out, so I figure I'd ask the pros for some help :p

Is it possible to use a regular expression to replace infinitely-nested parentheses and their contents with " " (a blank space)? For example:

(This (is (a (sentence) with) lots of nested) parentheses)

Thanks :)

Kor
07-23-2010, 11:48 AM
Like this?


<script type="text/javascript">
var str='(This (is (a (sentence) with) lots of nested) parentheses)';
str=str.replace(/\(|\)/g,'');
alert(str);
</script>


It is not very clear what you want to replace.

More about Regular Expressions:
http://lawrence.ecorp.net/inet/samples/regexp-intro.php

neochronomo
07-23-2010, 02:12 PM
I'll try to be more clear, with another example.

I want this:
Four score (and seven (years) ago) our fathers brought (forth onto) this continent

To turn into this:
Four score our fathers brought this continent


In other words, I want all parenthetical information removed; the parentheses and what they contain, even if nested.

Kor
07-23-2010, 04:21 PM
Yes. Interesting problem. First time I thought it is simple - a non-greedy RegExp:


<script type="text/javascript">
var str='Four score (and seven (years) ago) our fathers brought (forth onto) this continent';
str=str.replace(/\(.*?\)/g,'');
</script>

But that should work only in case there are no other inner parenthesis nested inside other parenthesis, so that in your case the result is:

'Four score ago) our fathers brought this continent'

Which is logical, but it is not what we need. :)

I promise to think more about that. And maybe someone else here sees a complete solution...

Kor
07-23-2010, 04:29 PM
I think I found a way. I am not sure it is the best possible solve, but it works, as far as I have seen:


<script type="text/javascript">
var str='Four score (and seven (years) ago) our fathers brought (forth onto) this continent';
while(str.match(/\(.*?\)/g)){
str=str.replace(/\(.[^\(]*?\)/g,'');
}
</script>

Kor
07-23-2010, 04:35 PM
And probably you need to remove the extra single spaces as well:


<script type="text/javascript">
var str='Four score (and seven (years) ago) our fathers brought (forth onto) this continent';
while(str.match(/\(.*?\)/g)){
str=str.replace(/\(.[^\(]*?\)/g,'');
}
str=str.replace(/\s\s/g,' ');
</script>

Philip M
07-23-2010, 05:54 PM
And perhaps perform a check for unmatched parentheses:-



<script type="text/javascript">
function removeParentheses() {

var str = 'Four score (and seven (years) ago) our fathers brought (forth onto) this continent';

var c = 0;
var n = 0;
for (var j=0 ; j < str.length ; j++) {
c = str.charAt(j);
if (c == "(") {n++}
if (c == ")") {n--}
}
if (n != 0) {
alert ("Error - unmatched parentheses");
return false;
}

while(str.match(/\(.*?\)/g)){
str=str.replace(/\(.[^\(]*?\)/g,'');
}
str=str.replace(/\s\s/g,' ');
alert (str);
}

removeParentheses();
</script>

Kor
07-23-2010, 10:09 PM
Good idea, Philip.

Old Pedant
07-23-2010, 11:02 PM
Hmmm....but what about this:


What ) about parens in text like ( this?

Your counting will find they are matched and yet nothing will be removed via the regexp's.

How about K.I.S.S.?? Just check for hangers-on *after* the replacement of matches:



<script type="text/javascript">
function removeParentheses()
{

var str = 'Four ) score (and seven (years) ago) our fathers brought (forth onto) this ( continent';

while(str.match(/\(.*?\)/g))
{
str = str.replace(/\(.[^\(]*?\)/g,'');
}
str=str.replace(/\s+/g,' ');

if ( str.match(/[\(\)]/) ) alert("Mismatched parentheses?");

alert(str);
}

removeParentheses();
</script>

Old Pedant
07-23-2010, 11:10 PM
A minor simplification that should help performance a tiny bit:


<script type="text/javascript">
function removeParentheses(str)
{
while( true )
{
var str2 = str.replace(/\(.[^\(]*?\)/g,'');
if ( str2 == str ) break;
str = str2;
}
str = str.replace(/\s+/g,' ');

if ( str.match(/[\(\)]/) ) alert("Mismatched parentheses?");
return str;
}

var test1 = 'Four score (and seven (years) ago) our fathers brought (forth onto) this continent';
alert( removeParentheses(test1) );

alert( removeParentheses("and ) simple ( test ) like this ( as well ") );

</script>

Old Pedant
07-23-2010, 11:14 PM
By the by, doing

str = str.replace(/\s\s/g, " ");

will *NOT* remove all extra spaces. For example, if there are 3 spaces (or more) in a row, that will consolidate each *pair* of spaces down to one, but the replaced text is not rescanned. So, for example, 9 spaces in a row would be consolidated to 5 spaces.

That's why I do

str = str.replace(/\s+/g, " ");

Probably even better would be


str = str.replace( /\s{2,}/g, " ");

mrhoo
07-24-2010, 05:30 AM
// I'm late to the party, but this method may do-


function stripParenths(s){
var rx=/\s*\([^)(]*\)\s*/;
while(rx.test(s)){
s= s.split(rx).join(' ');
}
return s;
// or to remove any stray parens: return s.replace(/[)(]/g,'');
}

//test

var str= 'Four score (and (seven (years)) ago) our fathers brought (forth unto) this continent';
alert(stripParenths(str))

/* returned value: (String)
Four score our fathers brought this continent
*/

Old Pedant
07-24-2010, 10:13 AM
Makes me nervous.

Look at the value of s after each iteration of the loop.

Surprise.

Can't help but wondering if there is some set of parens that would fool that code.

Philip M
07-24-2010, 11:57 AM
Hmmm....but what about this:


What ) about parens in text like ( this?

Your counting will find they are matched and yet nothing will be removed via the regexp's.


Perhaps that is what is desired.

var str = "What :-) about parens in text like 8-( this?" ;)



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum