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, "e;$1"e;+"e;white"e;);
Is there an alternative way to do this? It's harder since it's global

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,"e;$1 white"e;);
if(RegExp.$1!="e;big"e;) return "e;Original : "e; + s + "e;\r\nChanged : "e; + s1 + "e;\r\nMatch : "e; + RegExp.$1;
else return "e;Original : "e; + s + "e;\r\nNot Changed!"e;;
}
function RunIt()
{
sentences = Array("e;Toby is a spotted cat"e;,"e;Toby is a big spotted cat"e;,"e;Toby is a spotted fluffy cat and he is big"e;,"e;Not all big cats like Toby are spotted"e;)
for(i=0;i<4;i++)
alert(ReplaceDemo(sentencesї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
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
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"

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,"e;$1 white"e;);
match = RegExp.$1;
if(match.search(bigre)==-1) return "e;Original : "e; + s + "e;\r\nChanged : "e; + s1 + "e;\r\nMatch : "e; + RegExp.$1;
else return "e;Original : "e; + s + "e;\r\nNot Changed!"e;;
}
function RunIt()
{
sentences = Array("e;Toby is a spotted cat"e;,"e;Toby is a big spotted cat"e;,"e;Toby is a spotted fluffy cat and he is big"e;,"e;Not all big cats like Toby are spotted"e;)
for(i=0;i<4;i++)
alert(ReplaceDemo(sentencesїi]))
}
RunIt()
</script>
It looks like at last I am getting hang of it. 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 = "e;Toby is a spotted cat\r\n"e;;
theString += "e;Toby is a big spotted cat\r\n"e;;
theString += "e;Toby is a spotted fluffy cat and he is big\r\n"e;;
theString += "e;Not all big cats like Toby are spotted\r\n"e;;
newString = theString.replace(/^((?:.(?!big))*)spotted/gmi, "e;$1white"e;);
alert (newString);