[SOLVED] RegExp > JS Global S/R (Negative look behind alt

JavaScript and client side scripting.

Moderator: General Moderators

Post Reply
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

[SOLVED] RegExp > JS Global S/R (Negative look behind alt

Post by Chris Corbyn »

Hypothetically speaking... I need to replace "spotted" with "white" only if the word "spotted" doesn't come after "big" on the same line. I can see this being a no go with the lack of negative lookbehinds in JS.
(1)Is replaced
Toby is a spotted cat

(2)Isn't replaced
Toby is a big spotted cat

(3)Is replaced
Toby is a spotted fluffy cat and he is big

(4)Isn't replaced
Not all big cats like Toby are spotted

-----
So putting all that together, a global search replace should turn:

Toby is a spotted cat
Toby is a big spotted cat
Toby is a spotted fluffy cat and he is big
Not all big cats like Toby are spotted

Into:

Toby is a white cat
Toby is a big spotted cat
Toby is a white fluffy cat and he is big
Not all big cats like Toby are spotted
Something to the effect of (if only negative lookbehinds worked in JavaScript:

Code: Select all

string.replace(/(?>!big)(.*)(spotted)/gmi, &quote;$1&quote;+&quote;white&quote;);
Is there an alternative way to do this? It's harder since it's global :D
Last edited by Chris Corbyn on Mon Apr 11, 2005 5:38 am, edited 1 time in total.
User avatar
n00b Saibot
DevNet Resident
Posts: 1452
Joined: Fri Dec 24, 2004 2:59 am
Location: Lucknow, UP, India
Contact:

Post by n00b Saibot »

Hurrah! for the 1st time, I solved a RegExp problem.
Here the whole test code I ran. Works like a charm.

Code: Select all

<script>
var re = /(\w*\b) spotted/gi

function ReplaceDemo(s)
{
s1 = s.replace(re,&quote;$1 white&quote;);
if(RegExp.$1!=&quote;big&quote;) return &quote;Original : &quote; + s + &quote;\r\nChanged : &quote; + s1 + &quote;\r\nMatch : &quote; + RegExp.$1;
else return &quote;Original : &quote; + s + &quote;\r\nNot Changed!&quote;;
}

function RunIt()
{
sentences = Array(&quote;Toby is a spotted cat&quote;,&quote;Toby is a big spotted cat&quote;,&quote;Toby is a spotted fluffy cat and he is big&quote;,&quote;Not all big cats like Toby are spotted&quote;)
for(i=0;i<4;i++)
alert(ReplaceDemo(sentences&#1111;i]))
}
RunIt()
</script>
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

OK that work yeah thanks.... Only problem is that I need to split my document at each

Code: Select all

\r\n
and store each line in an array then use a loop to make it work.... this is gonna be very slow on a document with >300 lines for example....

Works in any case - well done :lol:

If anybody has a more efficient way please tell :?:
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Oh I should have said that big doesn't have to be immediately before spotted.

So
"Toby is a big dirty mangey spotted cat" :wink: also should fail....
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

(?>!big) isn't a conditional.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

feyd wrote:(?>!big) isn't a conditional.
Tut :) I meant (?<!big) - mistyped. I think it's supposed to go at the end too :?
User avatar
n00b Saibot
DevNet Resident
Posts: 1452
Joined: Fri Dec 24, 2004 2:59 am
Location: Lucknow, UP, India
Contact:

Post by n00b Saibot »

OK I tried this thing in the morning today and I got this working snip.

Code: Select all

<script>
var re = /(\w*\b.*) spotted/gi
var bigre = /big/i;

function ReplaceDemo(s)
{
s1 = s.replace(re,&quote;$1 white&quote;);
match = RegExp.$1;
if(match.search(bigre)==-1) return &quote;Original : &quote; + s + &quote;\r\nChanged : &quote; + s1 + &quote;\r\nMatch : &quote; + RegExp.$1;
else return &quote;Original : &quote; + s + &quote;\r\nNot Changed!&quote;;
}

function RunIt()
{
sentences = Array(&quote;Toby is a spotted cat&quote;,&quote;Toby is a big spotted cat&quote;,&quote;Toby is a spotted fluffy cat and he is big&quote;,&quote;Not all big cats like Toby are spotted&quote;)
for(i=0;i<4;i++)
alert(ReplaceDemo(sentences&#1111;i]))
}
RunIt()
</script>
It looks like at last I am getting hang of it. lol :lol:
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Oh BTW I solved this... forgot to mention..

Just one regxep (you just use e negative lookahead on EVERY character up to the pattern that's disallowed and then STOP here).

I believe logically this will do the same as a negative lookbehind and since JS doesn't support lookbehinds this is a good workaround - may be a useful to remember ;-)

Code: Select all

theString = &quote;Toby is a spotted cat\r\n&quote;;
theString += &quote;Toby is a big spotted cat\r\n&quote;;
theString += &quote;Toby is a spotted fluffy cat and he is big\r\n&quote;;
theString += &quote;Not all big cats like Toby are spotted\r\n&quote;;

newString = theString.replace(/^((?:.(?!big))*)spotted/gmi, &quote;$1white&quote;);

alert (newString);
Post Reply