5 Replies Latest reply on May 9, 2012 6:24 AM by John Hawkinson

    Escaping a carat symbol

    jkinsman Level 1

      I am trying to do a GREP search for a string of text between two carat symbols. This expression works when I test it using the Find Change Dialog but when I add it to my script, it no longer does anything. I am thinking there must be some special way to excape a carat in the script. Here is my code:

       

      app.findGrepPreferences.findWhat = "(\^)([^\^\r]*)(\^)";
      app.changeGrepPreferences.changeTo = "$2";
      app.changeGrepPreferences.appliedCharacterStyle = "Body Bold";
      

       

       

      Thanks for you help in advance

        • 1. Re: Escaping a carat symbol
          Marijan Tompa [tomaxxi] Level 4

          You have to use escaping like this:

          app.findGrepPreferences.findWhat = "(\\^)([^\\^\\r]*)(\\^)";

           

          Or you can convert RegExt expression to string like this:

          app.findGrepPreferences.findWhat = /(\^)([^\^\r]*)(\^)/.source;

          • 2. Re: Escaping a carat symbol
            jkinsman Level 1

            That was it. So all escaping has to have to backslashes? Why is that?

            • 3. Re: Escaping a carat symbol
              [Jongware] Most Valuable Participant

              There is. (Marijan answered that one.)

               

              Inside a script, all strings must obey Javascript syntax; and the backslash itself is a special Javascript string character; it also acts as 'escape' for the next character.

               

              You need to double all single backslashes, so they end up "inside" Javascript only once; and that is the string that is fed to InDesign's text search module.

               

              (FYI, there are a couple of excceptions to this rule. For Tab, New Line, and Hard Return, you ought to theoretically use '\\t', \\n', and '\\r', lest they get translated to the literal characters Tab, Newline, and Carriage Return. But I found you can leave these in with a single backslash, since ID's GREP module also recognizes these three characters as literal ones in a GREP string. You might get a weird display, though, when you call up the GREP Find box in the UI.)

              • 4. Re: Escaping a carat symbol
                John Hawkinson Level 5

                But don't double the backslashes! Use the regexp literal, tomaxxi's second example:

                 

                app.findGrepPreferences.findWhat = /(\^)([^\^\r]*)(\^)/.source;

                 

                It is much cleaner!

                • 5. Re: Escaping a carat symbol
                  [Jongware] Most Valuable Participant

                  Uh, and the explanation for that is? Because a literal RegExp is a primary Javascript object? But this is intended for use with InDesign, not "within" JS itself, so what happens with ID's added special characters?

                  • 6. Re: Escaping a carat symbol
                    John Hawkinson Level 5
                    Uh, and the explanation for that is? Because a literal RegExp is a primary Javascript object?

                     

                    Not quite sure what you mean by "that" -- it sounds like you answered your own question?

                    A Javascript Regexp Literal is a literal syntax in Javascript that does not require escaping backslashes (at least under normal circumstances), and that is a huge readability improvement over the other choices.

                     

                    But this is intended for use with InDesign, not "within" JS itself, so what happens with ID's added special characters?

                    Well, I'm sure it depends, but let's see. Looks like we're good for everything from 'A' to 'z' (including \,]\,^,_, and `) with the exception of a bare "\c", which isn't an "ID added special character."

                     

                    for (var i=0; i<58; i++) {
                        var c = String.fromCharCode(65+i);
                        var r = "\\"+c;
                        try { 
                           if ((new RegExp(r)).source !== r) { 
                              $.writeln("uhoh "+c);
                          }
                        } catch (e) {
                            $.writeln("Failed to construct /\\"+c+"/: "+e); 
                        } 
                    }
                    

                     

                    It's not like this has to work with every Javascript implementation out there, just ID's...