Page 1 of 1

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

Posted: Mon Apr 04, 2005 5:18 am
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

Posted: Mon Apr 04, 2005 7:56 am
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>

Posted: Mon Apr 04, 2005 9:11 am
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 :?:

Posted: Mon Apr 04, 2005 9:15 am
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....

Posted: Mon Apr 04, 2005 9:25 am
by feyd
(?>!big) isn't a conditional.

Posted: Mon Apr 04, 2005 12:46 pm
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 :?

Posted: Tue Apr 05, 2005 1:09 am
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:

Posted: Mon Apr 11, 2005 5:17 am
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);