Photoshop Javascript - Regular Expressions

Photoshop Script Snippets - Note: Full Scripts go in the Photoshop Scripts Forum

Moderators: Tom, Kukurykus

Andrew

Photoshop Javascript - Regular Expressions

Post by Andrew »

Well done Xbytor, you're quite right! I just tested it with the regexp tester on one of my help files (hence oridinary JS not the Adobe version) and it works as you describe (and as, before I did all my own testing, I would have expected).

I'm surprised to find a bug in regexp as it is so universal and I can see no reason for why Adobe would have needed to fiddle with it at all. But it is very useful to know that this is not normal regexp behaviour, perhaps we (you?) should report it as such at the Adobe forum so others know and Adobe can decide if it wants to take any notice or not.

Andrew
Mike Hale

Photoshop Javascript - Regular Expressions

Post by Mike Hale »

perhaps we (you?) should report it as such at the Adobe forum so others know and Adobe can decide if it wants to take any notice or not.

In adddition to the user to user forum, it might be helpful to post is here as well. This link is for reporting bugs and it might get more notice there.

http://www.adobe.com/misc/bugreport.html

Mike
Andrew

Photoshop Javascript - Regular Expressions

Post by Andrew »

Something I discovered the other day. You can reference a bracketed expression later in the same regexp expression using \n.

For example the following captures the part of the string in quotes regardless of whether single or double quotes are used:

Code: Select allalert('he said "Goodbye" and went out'.match(/(['"])[^'"]*\1/g));

This can also be useful with xml:

Code: Select alltest();

function test () {
   var string = "<exif:test>testvalue</exif:test>";
   var re = /<(exif:.+)>(.*)<\/\1/;
   var arr = re.exec(string);
   alert(arr);
}

Andrew
Andrew

Photoshop Javascript - Regular Expressions

Post by Andrew »

Another RegExp bug.

Code: Select allfunction test () {
   var str = 'test\ntest';
   var str1 = str.replace(/\n/,'');// str1 = testtest
   var str2 = str.replace(/\\n/,'');// str2 = test\ntest
}
test();

With normal Javascript it would be (and is, I just tested it) the other way round ie when you need to specify '\' as a character in it's own right it needs another '\' in front to make '\\'.

Andrew
Andrew

Photoshop Javascript - Regular Expressions

Post by Andrew »

I thought this was interesting enough to be worth reporting here. This is a real-world example from a script I am currently developing, so it is not set out in the easiest way possible as an example.

However, the crux of the matter is that in most cases you can build up a match RegExp either as a single RegExp 'match' method, or as a series of search RegExp's.

In my example which follows I compared the time required for each method and the search based approach proved to be around 3000 times faster to obtain exactly the same result.

Here is the string I am searching through:

bb/files/L1.dat

It countains (parts of) toSource renderings for four objects: ahsl0 - ahsl3;

Each object has four properties eg: ahsl0.elseif; ahsl0.condition; ahslo.ctext; ahsl0.pos.

What the overall function is doing is to capture those properties plus the object name (eg ahsl0) in a multi-D array.

Here's the code:

Code: Select allfunction processCommand (cStr) {
   var re0,re1,re2,re3,s0,s1,s2,s3;
   var sAr = []; var cmdAr = [];
   
   cStr = cStr.replace(/\r|\n|\t/g,'');
   // METHOD 1 USING SEARCH
   re0 = /\.elseif=(.(?!;ahsl\d+\.condition=))+/;
   re1 = /\.condition="(.(?!";ahsl\d+\.ctext=))+/;
   re2 = /\.ctext="(.(?!";ahsl\d+\.pos=))+/;
   re3 = /\.pos="(.(?!";))+/;
   while((s0 = cStr.search(re0)) != -1) {
      s1 = cStr.search(re1);
      s2 = cStr.search(re2);
      s3 = cStr.search(re3);
      sAr.push([
         cStr.substring(s0+8,re0.lastIndex+1),
         cStr.substring(s1+12,re1.lastIndex+1),
         cStr.substring(s2+8,re2.lastIndex+1),
         cStr.substring(s3+6,re3.lastIndex+1)]);
   }
   // END OF METHOD 1
   // METHOD 2 USING MATCH
   var re4 = /(ahsl\d+)\.elseif=(.+);\1\.condition="(.+)";\1\.ctext=\"(.+)\";\1\.pos=\"([ \w]+)\";/g;
   var nAr = [];
   while ((matches = re4.exec(cStr)) != null) {
      nAr.push([matches[2],matches[3],matches[4],matches[5]]);
   }
   // END OF METHOD 2
}


Using various Date variables at the start, after the first method and after the second method I compare the time taken. The average is 0 milliseconds for the first method and 3300 milliseconds for the second method. Reversing the order has no effect. You will see the specification of the match and search RegExps is pretty much equivalent.

While it can take more time to script multiple search RegExp's to achieve the same as a match RegExp it is likely to be well worth doing so.

Couple of details.

First, I take advantage of the working method for multiple passes of the same search RE variable that each pass starts AFTER the last character matched in the previous pass (see first while loop).

Second, to make the search based matching easier I use the lastIndex property of the search RegExp - when you search for a pattern the position returned will be the START of your pattern while the search RegExp lastIndex property will be the next position in the target string AFTER the match - so targetString.substring(searchpos,myRegExp.lastIndex) is the actual full match.

Andrew
SzopeN

Photoshop Javascript - Regular Expressions

Post by SzopeN »

http://ps-scripts.com/bb/viewtopic.php?t=434 could be updated: in CS4 the behavior of | in regexp have been fixed (returns 1 as expected)