• Login
Community
  • Login

Negative lookbehind regular expression not working on Notepad++

Scheduled Pinned Locked Moved Help wanted · · · – – – · · ·
43 Posts 6 Posters 1.6k Views
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D
    dr ramaanand @PeterJones
    last edited by dr ramaanand Apr 22, 2025, 11:36 PM Apr 22, 2025, 9:21 PM

    @PeterJones I have understood what @guy038 is trying to convey (and I have been using it). A template would be useful and this is an example: (xyz)(*SKIP)(*F)|(z) is like a negative look behind which skips finding any z if it is preceded by y or x (the order of the x and y need not be the same) but finds all other occurrences of z - post no.16 shows how he used it for the block I typed for testing at the top of this thread

    I would prefer a template like this:-

    (String1|String2)(MAIN Regex Search)(*SKIP)(*F)|(MAIN Regex Search)
                                                   |
    <------------- This I do NOT want ------------><- This I DO want ->
    
    D 1 Reply Last reply Apr 23, 2025, 6:13 AM Reply Quote 0
    • D
      dr ramaanand @dr ramaanand
      last edited by dr ramaanand Apr 23, 2025, 10:00 AM Apr 23, 2025, 6:13 AM

      @PeterJones We can add another line below the above RegEx explanation like this (to explain it better):-

      <------------- What I want to SKIP ------------><- What I want to MATCH ->
      
      D 1 Reply Last reply Apr 23, 2025, 10:41 AM Reply Quote 1
      • D
        dr ramaanand @dr ramaanand
        last edited by dr ramaanand Apr 23, 2025, 10:47 AM Apr 23, 2025, 10:41 AM

        @PeterJones The wonderful thing about the (*SKIP)(*F) method is that it can be used for negative look aheads also like this:-

        (MAIN Regex Search)(String1|String2)(*SKIP)(*F)|(MAIN Regex Search)
                                                       |
        <------------- What I want to SKIP ------------><-What I want to MATCH->
        
        P 1 Reply Last reply Apr 23, 2025, 1:01 PM Reply Quote 0
        • P
          PeterJones @dr ramaanand
          last edited by Apr 23, 2025, 1:01 PM

          @dr-ramaanand said in Negative lookbehind regular expression not working on Notepad++:

          The wonderful thing about the (*SKIP)(*F) method is that it can be used for negative look aheads also like this

          But pointless, because lookaheads (negative or positive) can have variable width, so if you want a lookahead, just use a lookahead.

          D 1 Reply Last reply Apr 23, 2025, 1:14 PM Reply Quote 2
          • D
            dr ramaanand @PeterJones
            last edited by Apr 23, 2025, 1:14 PM

            @PeterJones The (*SKIP)(*F) method can be of variable width but it can be used only for negative look aheads and negative look behinds

            A 1 Reply Last reply Apr 23, 2025, 1:56 PM Reply Quote 0
            • A
              Alan Kilborn @dr ramaanand
              last edited by Apr 23, 2025, 1:56 PM

              @dr-ramaanand

              Peter’s last point (which you missed) was that lookaheads are best done with native regex syntax, because it is more obvious that way.

              And he probably would have confused you less if he had left out (negative or positive) from his sentence; doing that doesn’t change the meaning.

              1 Reply Last reply Reply Quote 3
              • G
                guy038
                last edited by guy038 Apr 24, 2025, 10:38 AM Apr 24, 2025, 10:37 AM

                Hello, @peterjones and All,

                OK. I going to prepare a blog post regarding the (*SKIP)(*F) feature !

                However, be patient because I’ll try, first :

                • To find out some other pertinent examples from various regex sites

                • To propose alternatives to the (*SKIP)(*F) syntax when it’s possible !

                BR

                guy038

                D 1 Reply Last reply Apr 24, 2025, 12:22 PM Reply Quote 3
                • D
                  dr ramaanand @guy038
                  last edited by dr ramaanand Apr 24, 2025, 1:20 PM Apr 24, 2025, 12:22 PM

                  @guy038 please create the blog to show how to use the (*SKIP)(*FAIL) regular expression, not an alternative to it. @PeterJones may be able to create an alternative to it. If @PeterJones wants to still use his method for what I have typed as my block for testing, he can do it in 2 parts; first using the regular expression, (<span\b[^>]*?color\s*:\s*black[^>]*>\s*|<p\b[^>]*?color\s*:\s*black[^>]*>\s*<span\b[^>]*>\s*)\K(<code\s*style="background-color:\s*transparent;">) in the find field and a unique string (say for example, a unique name like, “Czeslawski”) in the replace field, he can replace the <code\s*style="background-color:\s*transparent;"> with that unique string. Then he can do what is needed to the other strings of <code\s*style="background-color:\s*transparent;"> and then again replace the unique string (“Czeslawski” in this case) with <code\s*style="background-color:\s*transparent;">. If it is something simple, this example should be sufficient: https://stackoverflow.com/questions/17286667/regular-expression-using-negative-lookbehind-not-working-in-notepad

                  1 Reply Last reply Reply Quote 0
                  • G
                    guy038
                    last edited by Apr 24, 2025, 1:51 PM

                    Hello, @dr-ramaanand,

                    When I said :

                    To propose alternatives to the (*SKIP)(*F) syntax when it’s possible !

                    I’m not talking about a work-around, using a several-steps regex, but, indeed, other direct regexes, without the (*SKIP)(*F) syntax, which are, sometimes, even shorter !

                    You’ll understand what I mean., sooner !

                    Best Regards,

                    guy038

                    D 1 Reply Last reply Apr 24, 2025, 4:50 PM Reply Quote 1
                    • D
                      dr ramaanand @guy038
                      last edited by Apr 24, 2025, 4:50 PM

                      @guy038 I will understand it only after you post that regular expression (RegEx) here

                      D 1 Reply Last reply Apr 26, 2025, 9:50 AM Reply Quote 0
                      • D
                        dr ramaanand @dr ramaanand
                        last edited by Apr 26, 2025, 9:50 AM

                        This post is deleted!
                        1 Reply Last reply Reply Quote 0
                        • G
                          guy038
                          last edited by Apr 26, 2025, 1:20 PM

                          Hello, @peterjones and All,

                          Peter, Done ! Refer to :

                          https://community.notepad-plus-plus.org/topic/26812/generic-regex-how-to-use-the-couple-of-backtracking-control-verbs-skip-fail-or-skip-f-in-regexes

                          I also added a link to this post in your FAQ: Generic Regular Expression (regex) Formulas post.

                          Best Regards,

                          guy038

                          D 1 Reply Last reply Apr 26, 2025, 1:57 PM Reply Quote 3
                          • D
                            dr ramaanand @guy038
                            last edited by dr ramaanand Apr 26, 2025, 5:23 PM Apr 26, 2025, 1:57 PM

                            @guy038 So, if you have an alternative method to the (*SKIP)(*FAIL) method for the block posted right at the top of this thread for testing to match the same string you posted in post#16 above, please post it here

                            D 1 Reply Last reply Apr 27, 2025, 10:11 AM Reply Quote 0
                            • D
                              dr ramaanand @dr ramaanand
                              last edited by dr ramaanand Apr 27, 2025, 11:55 AM Apr 27, 2025, 10:11 AM

                              @guy038 you can use the idea mentioned at www.drregex.com/2019/02/variable-length-lookbehinds-actually.html?m=1 if you please, for the above RegEx. @PeterJones can include that formula in the Notepad++ manual also, if he pleases.

                              A 1 Reply Last reply Apr 27, 2025, 11:25 AM Reply Quote 0
                              • A
                                Alan Kilborn @dr ramaanand
                                last edited by Alan Kilborn Apr 27, 2025, 11:33 AM Apr 27, 2025, 11:25 AM

                                @dr-ramaanand said:

                                www.drregex.com/2019/02/variable-length-lookbehinds-actually.html?m=1

                                Doesn’t appear to be a valid link, in fact, it seems to point back to the N++ Community site??

                                THIS is probably the correct link.

                                D 1 Reply Last reply Apr 27, 2025, 12:15 PM Reply Quote 1
                                • D
                                  dr ramaanand @Alan Kilborn
                                  last edited by dr ramaanand Apr 27, 2025, 12:21 PM Apr 27, 2025, 12:15 PM

                                  @guy038 The answer by User Doqnach mentioned at https://stackoverflow.com/questions/25563891/variable-length-look-behind can be used as an example.

                                  A 1 Reply Last reply Apr 27, 2025, 12:29 PM Reply Quote 0
                                  • A
                                    Alan Kilborn @dr ramaanand
                                    last edited by Apr 27, 2025, 12:29 PM

                                    @dr-ramaanand said:

                                    The answer by User Doqnach mentioned at … can be used as an example.

                                    Well, trying that (/(?=(?=(?'a'[\s\S]*))(?'b'eat_(?:apple|pear|orange)_(?=\k'a'\z)|(?<=(?=x^|(?&b))[\s\S])))today|yesterday) in Notepad++ yields:

                                    bf2380ce-2d50-4d34-8670-d833b3f43479-image.png

                                    This is an error message I don’t think I’ve seen before.

                                    Note that I tried it on a smallish file where nothing would have matched.

                                    D 1 Reply Last reply Apr 27, 2025, 12:39 PM Reply Quote 0
                                    • D
                                      dr ramaanand @Alan Kilborn
                                      last edited by dr ramaanand Apr 27, 2025, 3:46 PM Apr 27, 2025, 12:39 PM

                                      @Alan-Kilborn That RegEx should be (?=(?=(?'a'[\s\S]*))(?'b'eat_(?:apple|pear|orange)_(?=\k'a'\z)|(?<=(?=x^|(?&b))[\s\S])))today|yesterday - I corrected it on stackoverflow but my edit is awaiting moderation (others can see it with my corrections only after my edit gets approved). For your information, those are positive look behinds with a capture group named ‘a’ and a capture group named ‘b’ and need to be changed to negative look behinds. I am unable to skip anything with this or this . I want the result to be like in post#16

                                      D 1 Reply Last reply Apr 27, 2025, 5:31 PM Reply Quote 0
                                      • D
                                        dr ramaanand @dr ramaanand
                                        last edited by dr ramaanand Apr 27, 2025, 5:32 PM Apr 27, 2025, 5:31 PM

                                        This post is deleted!
                                        1 Reply Last reply Reply Quote 0
                                        • G
                                          guy038
                                          last edited by guy038 Apr 27, 2025, 7:16 PM Apr 27, 2025, 6:35 PM

                                          Hello, @dr-ramaanand and All,

                                          Ah, I just having some spare time to answer your specific problem !

                                          As I said in a previous post, you cannot use look-behinds as they do NOT support variable quantifiers ! That’s why I proposed a method with the ((SKIP)(*F) feature, which works properly.


                                          In order to found out other methods, let’s begin with a simplified problem :

                                          Starting with this INPUT text :

                                          DEF  ABCDEF   ABC     DEF  ABCDEF   XYZDEF   ABCDEF
                                          

                                          The following regex S/R :

                                          FIND (?-is)ABCDEF(*SKIP)(*F)|DEF

                                          REPLACE 12345

                                          Matches only the DEF string when NOT preceded with the ABC string

                                          After the replacement, we get this OUTPUT :

                                          12345  ABCDEF   ABC     12345  ABCDEF   XYZ12345   ABCDEF
                                          
                                          • If DEF is preceded by ABC, NO replacement occurs

                                          • If DEF is NOT preceded by ABC it replaces the string DEF by the string 12345


                                          Now, using the same INPUT text :

                                          The following regex S/R :

                                          FIND (?-is)ABCDEF\K|(DEF)

                                          REPLACE ?{1}12345

                                          • Detect an empty match, when the DEF string is preceded by the ABC string

                                          • Detect some selected text, when the DEF string is NOT preceded by the ABC string

                                          But, due to the group, in the final part of the regex and due to the conditional replacement, it would produce this OUTPUT :

                                          12345  ABCDEF   ABC     12345  ABCDEF   XYZ12345   ABCDEF
                                          

                                          As previously :

                                          • if DEF is preceded by ABC, NO replacement occurs

                                          • if DEF is NOT preceded by ABC it replaces the string DEF by the string 12345


                                          Let’s apply this new regex S/R to your problem. Thus, from this regex :

                                          FIND (?:<span\b[^>]*?color\s*:\s*black[^>]*>\s*|<p\b[^>]*?color\s*:\s*black[^>]*>\s*<span\b[^>]*>\s*)<code\s*style="background-color:\s*transparent;">(*SKIP)(*F)|<code\s*style="background-color:\s*transparent;">

                                          If we simply replace the (*SKIP)(*F) part by \K AND if we put all the right branch of the alternative within a group, this S/R becomes as :

                                          FIND (?:<span\b[^>]*?color\s*:\s*black[^>]*>\s*|<p\b[^>]*?color\s*:\s*black[^>]*>\s*<span\b[^>]*>\s*)<code\s*style="background-color:\s*transparent;">\K|(<code\s*style="background-color:\s*transparent;">)

                                          REPLACE ?1[REPLACED text]

                                          When just searching, the non-interesting matches will be notified as an empty match and the correct matches will be notified as selected text.

                                          And if a global replacement occur, with the Replace All button, this regex would just replace the same occurrences as with the (*SKIP)(*F) method !

                                          Try against your INPUT text, pasted in a new tab : you should get 2 empty matchs and 4 selected range of characters. And, after replacement you’ll left with four zones [REPLACED text].

                                          <html>
                                          <p style="font-family: &quot;verdana&quot;; font-size: 18px; color: black; line-height: 18px; text-align: justify; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: cyan;"><span style="font-size: 13.5pt; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"><code style="background-color: transparent;">•••••<b>some text here</b></code></span></p>
                                          <span><span style="font-size: 13.5pt; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;; background-color: cyan;"><code style="background-color: transparent;"><b>some text here</b></code></span>
                                          
                                          
                                          <code style="background-color: transparent;">
                                          
                                          
                                          <p style="font-family: &quot;verdana&quot;; font-size: 18px; color: cyan; line-height: 18px; text-align: justify; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: cyan;"><span style="color: black; font-size: 13.5pt; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"><code style="background-color: transparent;">•••••<b>some text here</b></code></span></p>
                                          
                                          
                                          <span><span style="font-size: 13.5pt; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;; background-color: cyan;"><code style="background-color: transparent;"><b>some text here</b></code></span>
                                          
                                          
                                          <p style="font-family: &quot;verdana&quot;; font-size: 18px; color: cyan; line-height: 18px; text-align: justify; font-style: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; background-color: navy;"><span style="font-size: 13.5pt; font-family: &quot;Verdana&quot;,&quot;sans-serif&quot;;"><code style="background-color: transparent;"><b>some text here</b></code></span></p>
                                          </html>
                                          

                                          Now, it’s not the end of the story ! Imagine that, against the same INPUT text, below :

                                          DEF  ABCDEF   ABC     DEF  ABCDEF   XYZDEF   ABCDEF
                                          

                                          We use this simplified regex S/R :

                                          FIND (?-is)ABC\KDEF|(DEF)

                                          REPLACE ?{1}12345

                                          Note that, this time, the \K is placed before the string DEF

                                          So, it would match any string DEF, whatever it’s preceded or NOT by the ABC string

                                          But, due to the group, in the final part of the regex and due to the conditional replacement, We would get this new OUTPUT text, after a click on the Replace All button

                                          12345  ABC   ABC     12345  ABC   XYZ12345   ABC
                                          
                                          • if DEF is preceded by ABC, it replaces the string ABCDEF by the string ABC

                                          • if DEF is NOT preceded by ABC it replaces the string DEF by the string 12345

                                          This S/R is a variant of the previous one which may interest you in some cases !


                                          In short, I cannot imagine, presently, other methods than the two above, with (SKIP)(*F) or \K

                                          Remember, that the look-arounds structure does not seem appropriate to your style of search !

                                          Best Regards,

                                          guy038

                                          D 1 Reply Last reply Apr 27, 2025, 8:43 PM Reply Quote 1
                                          31 out of 43
                                          • First post
                                            31/43
                                            Last post
                                          The Community of users of the Notepad++ text editor.
                                          Powered by NodeBB | Contributors