18

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?

1

2 Answers 2

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

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

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