user1414235
user1414235

Reputation: 23

How negative lookbehind works in below example?

Why on applying regular expression(rx) on data(d) gives output(o) ?
Regular expression (rx):

s/(?<!\#include)[\s]*\<[\s]*([^\s\>]*)[\s]*\>/\<$1\>/g

Data (d):

#include  <a.h>  // 2 spaces after e

output (o):

#include <a.h>  // 1 space is still there

Expected output is:

#include<a.h>  // no space after include

Upvotes: 0

Views: 78

Answers (3)

Casimir et Hippolyte
Casimir et Hippolyte

Reputation: 89604

As an aside comment, you can use this pattern which doesn't use the lookbehind:

s/(?:#include\K|\G)(?:\s+|(<|[^\s><]+))/$1/g

pattern details:

(?:              # open a non capturing group
    #include\K   # match "#include" and reset it from the match result
  |              # OR
    \G           # a contiguous match
)                # close the non capturing group
(?:          
    \s+          # white characters (spaces or tabs here) 
  |              # OR
    (            # capturing group
        <
      |
        [^\s><]+ # content inside brackets except spaces (and brackets)
    )
)

The search stop at the closing bracket since it is not describe in the pattern and since there is no more contiguous matches until the next #include.

Upvotes: 0

Tim Pietzcker
Tim Pietzcker

Reputation: 336428

The condition (?<!\#include) is true as soon as you've passed the first of the two spaces, therefore the match starts there.

#include  <a.h>
         ^^^^^^- matched by your regex.

That means the space is not removed by your replace operation.

If you use a positive lookbehind assertion instead, you get the desired result:

s/(?<=#include)\s*<\s*([^\s>]*)\s*>/<$1>/g;

which can be rewritten to use the more efficient \K:

s/#include\K\s*<\s*([^\s>]*)\s*>/<$1>/g;

Upvotes: 6

sepp2k
sepp2k

Reputation: 370407

?<!\#include)[\s] is a space that is not directly preceded by #include. The first space in #include <a.h> is directly preceded by #include, so it isn't matched. The second one isn't (it's preceded by the other space), so that's where the match starts.

Upvotes: 2

Related Questions