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?
- 807,993
- 194
- 1,674
- 2,175
- 7,480
- 19
- 65
- 100
-
For the why part, see [Why does my regular expression work in X but not in Y?](http://unix.stackexchange.com/questions/119905/why-does-my-regular-expression-work-in-x-but-not-in-y) – Gilles 'SO- stop being evil' May 04 '14 at 21:05
2 Answers
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"
- 150,973
- 38
- 327
- 406
-
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 04 '14 at 16:57
-
7
-
It goes with saying that you need to put the negative look*behind* before the pattern. An example: `\(some\)\@<!thing` Will match `thing` and `everything` and `nothing`, but not `something`. – dwanderson Mar 07 '17 at 21:26
(?!\.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).
- 150,973
- 38
- 327
- 406
- 522,931
- 91
- 1,010
- 1,501
-
1I think what regex library which `less` uses is depended on compiled time. – cuonglm May 04 '14 at 18:32
-
-
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 05 '14 at 06:11
-
1@Gnouc, it prints the name of the regex library with `less --version`. – Stéphane Chazelas May 05 '14 at 06:28
-
I use Ubuntu 12.04 LTS and with `less --verion`, it only prints `less 444` along with Copyright. – cuonglm May 05 '14 at 06:45
-
@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. – Stéphane Chazelas May 05 '14 at 07:52