Negative lookbehind/ahead assertions in Linux less pager (or vim)
Solution 1
In vim
, you can do like this:
/index\(\.php\)\@!
For more details, in command mode, try :h \@
:
\@! Matches with zero width if the preceding atom does NOT match at the
current position. /zero-width {not in Vi}
Like '(?!pattern)" in Perl.
Example matches
foo\(bar\)\@! any "foo" not followed by "bar"
a.\{-}p\@! "a", "ap", "aap", "app", etc. not immediately
followed by a "p"
if \(\(then\)\@!.\)*$ "if " not followed by "then"
Solution 2
(?!\.php)
is a perl regexp operator. less
generally uses the system's POSIX regexp API, so typically GNU extended regular expressions on a GNU system, vim
uses vim
regular expressions.
In vim
, as already shown by cuonglm, the equivalent of index(?!\.php)
would be index\(\.php\)\@!
or \vindex(\.php)@!
.
For less
, at compile time, you can choose the regex library/API and as a result the regex type to use:
--with-regex={auto,gnu,pcre,posix,regcmp,re_comp, regcomp,regcomp-local,none} Select a regular expression library auto
By default though, less
will use POSIX regcomp
with REG_EXTENDED, so you'll get the extended regular expressions of your system, so typically something similar as with grep -E
.
In GNU extended regexp, there's no equivalent look behind or look ahead operator.
You could do it the hard way:
index($|[^.]|\.($|([^p]|p($|([^h]|h($|[^p]))))))
With less
, you could possibly use the &
key to filter out the lines containing index.php
(&!index\.php
), and then search for index
(/index
). (you'd still miss the other instances of index
that appear on a line also containing index.php
).
Related videos on Youtube
Gregg Leventhal
Updated on September 18, 2022Comments
-
Gregg Leventhal over 1 year
I want to find all instances of "index" not followed by .php in a log using
less
./index(?!\.php)
does not work. Is this possible? What is the regex for less and vim (do they differ?). Is this not possible with these application's respective regex libraries?-
Admin about 10 yearsFor the why part, see Why does my regular expression work in X but not in Y?
-
-
Gregg Leventhal about 10 yearsBeautiful! Any idea for less? This doesn't work in less. I wish regex behavior was PCRE everywhere, but alas it isn't.
-
cuonglm about 10 yearsI think what regex library which
less
uses is depended on compiled time. -
Stéphane Chazelas about 10 years@Gnouc, you're right, it even now supports PCRE it seems.
-
cuonglm about 10 yearsYeah, we can check if
less
usesPCRE
by parsing output ofldd $(which less)
. But with other library, do you know any way to check? -
Stéphane Chazelas about 10 years@Gnouc, it prints the name of the regex library with
less --version
. -
cuonglm about 10 yearsI use Ubuntu 12.04 LTS and with
less --verion
, it only printsless 444
along with Copyright. -
Stéphane Chazelas about 10 years@Gnouc, yes, it looks like it's only included when explicitly specified at compile time. So if you see nothing, that means less was built with the default.
-
lanoxx about 9 yearsAlso note the syntax for negativ lookbehind:
\@<!
-
dwanderson about 7 yearsIt goes with saying that you need to put the negative lookbehind before the pattern. An example:
\(some\)\@<!thing
Will matchthing
andeverything
andnothing
, but notsomething
.