sebelk
sebelk

Reputation: 644

Look behind regex in one-liner perl

I'm trying to make a one-liner script that prints when github is not behind golang.

For example, java is a language used in github should match, but golang is a language used in github shouldn't match.

I've tried the expression /(?<!golang).*github/, but it doesn't work.

echo "golang is a language used in github" |
    perl -nle'print /(?<!golang).*github/ ? "match" : "no match"'

This prints match instead of no match.

How can I do that using "negative look-behind" in Perl?

(Using Perl v5.28.1)

Upvotes: 0

Views: 420

Answers (3)

user7712945
user7712945

Reputation:

improving Bohemian's,

/^(?!.*golang.*github).*github/

Upvotes: 0

Silvar
Silvar

Reputation: 705

Your expression matches all strings with the word "github" in them. Let's see why:

/(?<!golang).*github/

will match as long as Perl can adjust the .* to match just enough characters to not run into a situation where it's immediately preceded by golang. Regexes being greedy, the .* will match as much as it can while still having the rest of the pattern match.

So if your string is

golang is a language used in github

The regex can match by assigning string to different parts:

  • (?<!golang) matches at the beginning of the string
  • .* gets "golang is a language used in"
  • github gets "github"

A potentially costly way to accomplish what you wanted is:

/^(?:(?!golang).)*github/

It works by making sure none of the characters preceding "github" begin the sequence "golang".

So

echo "java is a language used in github" | perl -ne 'print q!Not golang: !, /^(?:(?!golang).)*github/ ? q!true! : q!false!'

will print out Not golang: true while

echo "golang is a language used in github" | perl -ne 'print q!Not golang: !, /^(?:(?!golang).)*github/ ? q!true! : q!false!'

will print out Not golang: false.


Another (less obfuscated) way is to do two consecutive tests:

/^(.*)github/  and  $1 !~ /golang/

If you're doing tens or hundreds of thousands of lines, maybe test both ways to find which is faster?

Upvotes: 3

Bohemian
Bohemian

Reputation: 425238

Just use a negative look ahead anchored to start:

^(?!.*golang).*github

Upvotes: -1

Related Questions