20

I need to perform regex query replace, such that

foo in foo bar is matched, but foo in foo baz is not. Normally I would use regex look ahead, e.g. foo(?=bar).

However, it seems like Emacs cannot do this? Vim seems capable, but evil mode in spacemacs cannot.

Dan
  • 32,584
  • 6
  • 98
  • 168
Heisenberg
  • 433
  • 4
  • 9
  • There's also this: https://github.com/gamesun/emacs-regex-lookaround, but I didn't try building with this patch, and it looks like it's been a while. – wvxvw May 16 '17 at 03:35
  • Shelling out to `perl` can work in some use cases. – HappyFace Sep 19 '21 at 07:25

2 Answers2

18

No, Emacs regular expressions do not support arbitrary zero-width look-ahead/behind assertions.

n.b. Evil and Spacemacs (like all elisp libraries) are irrelevant when it comes to questions about the Emacs Lisp language implementation.

phils
  • 48,657
  • 3
  • 76
  • 115
  • So is it impossible to replace `foo` in `foobar` but not in `foobaz`? This is a common enough operation that I thought there must be a solution. Perhaps looking ahead and behind is the wrong approach? – Heisenberg May 14 '17 at 07:36
  • 1
    This isn't strictly equivalent, but replacing `foo\(bar\)` with `baz\1` will be sufficient in all cases where `bar` didn't contain further matches. – phils May 14 '17 at 08:37
  • If you're writing elisp, you have lots of flexibility, and if you're replacing interactively you can invoke arbitrary elisp during replacements, so ultimately there are ways to do these things. Just not as conveniently as you might do with those assertions. – phils May 14 '17 at 08:41
  • e.g.: replacing `foo` with `\,(if (looking-at "bar") "baz" \&)` will replace `foo` with `baz` if the following text is `bar` (and replace `foo` with `foo` otherwise). Which still isn't the same thing as only *matching* `foo` when it's followed by `bar`, but it's another option. – phils May 14 '17 at 08:48
  • I guess this is like what you said above, but it seems like you can type: C-S-M-% foo \\(bar\\) RET FOO \1 RET to replace all foo bar with FOO bar, but leave all foo baz alone. Is this missing some thing you wanted? – John Kitchin May 14 '17 at 16:09
6

https://github.com/benma/visual-regexp-steroids.el/

Visual regexp steroids allows you to replace, search, etc. using python regex. Python regex has support for look ahead and look behind.

It even highlights the regexp expressions for you.

regexp example

KhalfaniW
  • 337
  • 4
  • 8
  • Well, highlighting is also available without that, at least I have it in Doom, but good tip :) – xeruf Jul 03 '21 at 17:03