Menu

greedy and non-greedy reg ex

DoGooder
2007-11-27
2012-11-13
  • DoGooder

    DoGooder - 2007-11-27

    I can't see if NPP supports this or not.

    It seems to do a greedy reg ex only.

    I want it to do a non-greedy.

    I'm trying to remove all <font.....> tags from an HTML document.

    So, searching for "<font.+>" selects this text example:

    <font color="#FF0000"><b><font face="Verdana, Arial, Helvetica, sans-serif" size="2">

    When I really only want:

    <font color="#FF0000">

    If it doesn't support this, then why doesn't it when SciTE and Scintilla proper do?

     
    • Nobody/Anonymous

      Answered my own question--yes, you can use a capture/call back, up to nine instances for a single sweep.

           Find what: <font[^>]*>(.*)</font>
           Replace with: <span class="no-longer-deprecated">\1</span>

      The \1 provides the call back.

      See http://notepad-plus.sourceforge.net/uk/regExpList.php for a list of all regex that works with N++.

       
    • Nobody/Anonymous

      How about "<font[^>]+>", smart guy?

       
      • HappyDog

        HappyDog - 2007-11-27

        How does that solve the general case of ungreedy matches, smart guy?

        E.g. Matching the closing tag ("/<font[^>]*>.*</font>/U")

         
        • Nobody/Anonymous

          why wouldn't this work?

          <font[^>]*>[^<]*</font>

          (and, both of you, putting a comma before smart guy (as in "how's this, smart guy") is bad form)

           
          • HappyDog

            HappyDog - 2007-11-27

            > why wouldn't this work?

            > <font[^>]*>[^<]*</font>

            Because it won't match strings like "<font>This is some <b>bolded</b> text.</font>".

            > (and, both of you, putting a comma before smart guy
            > (as in "how's this, smart guy") is bad form)

            Why?  I wasn't asking who the smart guy was?

            - FartingUncle

             
            • Nobody/Anonymous

              >> <font[^>]*>[^<]*</font> 

              >Because it won't match strings like "<font>This is some <b>bolded</b> text.</font>".

              You're right - but you first offered <font[^>]*>.*</font> which does match the bolded sequence.
              So I'm not sure what we are having trouble matching.

              >> (and, both of you, putting a comma before smart guy 
              >> (as in "how's this, smart guy") is bad form)

              >Why? I wasn't asking who the smart guy was?

              Are you saying it's better with the comma smart guy?

               
              • HappyDog

                HappyDog - 2007-11-28

                >>> <font[^>]*>[^<]*</font> 

                >> Because it won't match strings like "<font>This is some <b>bolded</b> text.</font>". 

                > You're right - but you first offered <font[^>]*>.*</font>
                > which does match the bolded sequence. So I'm not sure what we are having trouble
                > matching.

                <font[^>]*>.*</font> is an (admittedly, unescaped - it should have been <font[^>]*>.*<\/font>) regex that matches the contents of a pair of opening/closing font tags, such as that given in the example.  It doesn't match the bolded sequence (unless I've misunderstood your point there).

                The other example given: <font[^>]*>[^<]*</font> would not match the above text, because there is an open-angle-bracket before the closing font tag, so the regex would fail.

                >>> (and, both of you, putting a comma before smart guy 
                >>> (as in "how's this, smart guy") is bad form) 

                >>Why? I wasn't asking who the smart guy was?

                >Are you saying it's better with the comma smart guy?

                Who's "the comma smart guy"?

                - FartingUncle

                 
                • Nobody/Anonymous

                  Do we have any way to call back in our replace tag?

                  Find: <font[^>]*>(.*)</font>

                  Replace: <font>{$1}</font>

                   
                  • Nobody/Anonymous

                    Yes, use backslash + number instead of {$#}.

                    Replace: <font>\1</font>

                     
    • Harry

      Harry - 2007-11-28

      It must be a newer (or older, doubtfull) version of scintilla and scite then, the regex engine for Npp's scintilla is, afaik, hardcoded to be greedy (read it in one of the comments when I was looking for an answer to the newline problem, but I figured the problem didnt really exists as TextFX was there ;)). You can browse the SVN, it should be in there somewhere. I found the behaviour to be doubtfull too, but its confined to a single line anyway so the problem is generally probably not too big (not in your case though). See if the TextFX regex engine handles it better, I think it uses a different one from the scintilla engine.

       
    • Nobody/Anonymous

      > <font[^>]*>.*</font> is an (admittedly, unescaped - it should have been <font[^>]*>.*<\/font>)
      > regex that matches > the contents of a pair of opening/closing font tags, such as that given
      > in the example. It doesn't match the bolded sequence (unless I've misunderstood your point there).

      Actually, it does match/find the bolded sequence (ie: "<font>This is some <b>bolded</b> text.</font>")
      whether the "/" is escaped or not (it doesn't need to be escaped).

      > The other example given: <font[^>]*>[^<]*</font> would not match the above text, because there
      > is an open-angle-bracket before the closing font tag, so the regex would fail.

      What I gave, the "<font[^>]*>[^<]*</font>", I admit isn't going to be useful on its own.
      However, it isn't "greedy".  Given the greedy regular expression implemention in N++
      (which I think is probably desirable), one might want to start with non-greedy
      expressions and eliminate the nested/inner matching data and then look/search to see what's
      left before completing the necessary replacement.  I suspect there isn't much that can't be
      accomplished this way.

      >> Who's "the comma smart guy"?

      I, too, can run a lot of commas for the, not so, smart guys?

       
      • Nobody/Anonymous

        > I, too, can run a lot of commas for the, not so, smart guys?

        You are asking me? Don't you know that for yourself, smart guy?

        Will the next regex be of any help?

        <font.+</font>

         
        • Nobody/Anonymous

          It seems this regex is only as greedy as the line is long. It will match the last </font> on the same line and, if it is not on the same line, it won't find a match.

           
          • Nobody/Anonymous

            > It seems this regex is only as greedy as the line is long. It will match the last </font> on the same line and, if it is not on the same line, it won't find a match.

            very true - but for many xhtml files it would be necessary to remove the line breaks before doing the replacing

            but your general point is a plus having regex greedy

             
            • Nobody/Anonymous

              If you want to _only_ remove all <font...> and </font> tags, how about the next regex?

              <[/]*font[^>]*>

              It removes <font...>, </font...> and even <//font...> and so on tags _only_, without worrying about matching opening and closing tags and whatever is after the font word inside the closing >.

               
              • Nobody/Anonymous

                yes that would be a likely last step for someone manually changing HTML type formatting to a better new way (CSS)