14

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?

22

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"
  • Beautiful! Any idea for less? This doesn't work in less. I wish regex behavior was PCRE everywhere, but alas it isn't. – Gregg Leventhal May 4 '14 at 16:57
  • 7
    Also note the syntax for negativ lookbehind: \@<! – lanoxx Mar 17 '15 at 12:33
  • 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. – dwanderson Mar 7 '17 at 21:26
7

(?!\.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).

  • 1
    I think what regex library which less uses is depended on compiled time. – cuonglm May 4 '14 at 18:32
  • @Gnouc, you're right, it even now supports PCRE it seems. – Stéphane Chazelas May 5 '14 at 6:04
  • 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? – cuonglm May 5 '14 at 6:11
  • 1
    @Gnouc, it prints the name of the regex library with less --version. – Stéphane Chazelas May 5 '14 at 6:28
  • I use Ubuntu 12.04 LTS and with less --verion, it only prints less 444 along with Copyright. – cuonglm May 5 '14 at 6:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.