Negative lookbehind/ahead assertions in Linux less pager (or vim)

5,544

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).

Share:
5,544

Related videos on Youtube

Gregg Leventhal
Author by

Gregg Leventhal

Updated on September 18, 2022

Comments

  • Gregg Leventhal
    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?

  • Gregg Leventhal
    Gregg Leventhal about 10 years
    Beautiful! Any idea for less? This doesn't work in less. I wish regex behavior was PCRE everywhere, but alas it isn't.
  • cuonglm
    cuonglm about 10 years
    I think what regex library which less uses is depended on compiled time.
  • Stéphane Chazelas
    Stéphane Chazelas about 10 years
    @Gnouc, you're right, it even now supports PCRE it seems.
  • cuonglm
    cuonglm about 10 years
    Yeah, we can check if less uses PCRE by parsing output of ldd $(which less). But with other library, do you know any way to check?
  • Stéphane Chazelas
    Stéphane Chazelas about 10 years
    @Gnouc, it prints the name of the regex library with less --version.
  • cuonglm
    cuonglm about 10 years
    I use Ubuntu 12.04 LTS and with less --verion, it only prints less 444 along with Copyright.
  • Stéphane Chazelas
    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
    lanoxx about 9 years
    Also note the syntax for negativ lookbehind: \@<!
  • dwanderson
    dwanderson about 7 years
    It goes with saying that you need to put the negative lookbehind before the pattern. An example: \(some\)\@<!thing Will match thing and everything and nothing, but not something.