6

Let's say I want to replace the string "Vector" by "VectorBase", but there are existing instances of "VectorBase". So I would like to omit "VectorBase". What is an elegant way to achieve this?

An easy way is to do ignore the condition and do the replacement and at the end replace all instances of BaseBase by Base. I'm looking for a better way to achieve this.

1
  • 1
    What you are looking for is made less clear by your saying that you want an "elegant" way and "a better way", without specifying what you mean by those conditions. Perhaps just ask for a way, and then you can choose which one(s) you think best.
    – Drew
    Jan 18, 2019 at 4:25

3 Answers 3

9

Try \_<Vector\_>. The \_< construct matches the empty string, but only at the beginning of a symbol. \_> is the same, but at the end of a symbol. What is a "symbol" depends on the buffer's syntax table; in programming language modes it's meant to be what the language treats as a symbol or identifier. You can also use \<Vector\> or \bVector\b to match a whole “word”, but that typically matches the Vector in Vector_Base, whereas \_<Vector\_> matches in Vector+1 but not in Vector_Base.

See Backslash Constructs in Regular Expressions for more information.

2
  • @Gilles: thanks! TIL something new.
    – NickD
    Jan 18, 2019 at 18:06
  • I really like this answer and Giles's edit. The other answers are good too!
    – hrkrshnn
    Jan 19, 2019 at 14:18
7

Another simple trick you can use is to match both Vector and VectorBase, and replace them both with VectorBase.

Vector\(Base\)? → VectorBase

More complicated cases can be handled by using elisp in the replacement. For example, the following replaces "Vector" with "Array" unless it was "VectorBase", in which case it 'keeps' it as "VectorBase" (i.e. replaces it with the matched string).

Vector\(Base\)? → \,(if \1 \& "Array")

Which is similar (in terms of the end result) to what can be done with arbitrary look-around assertions (in regexp languages which support those).

4

One simple, very old-school way is to do multiple replacement passes:

  1. Replace VectorBase by, say AAAA (some string with chars you're sure don't already occur somewhere).

  2. Replace Vector by VectorBase.

  3. Replace AAAA by VectorBase.

This works for replace-all and query-replace. It's pretty fail-safe and doesn't require any complex matching or fancy replacement regexp.

However: It's important that you first check that there are not already some occurrences of any chars of the string you're thinking of using as the temporary replacement (e.g. AAAA). If there are already such occurrences then choose a different string. ;-) (I typically use a string such as ^G (a Control-G character), input in the minibuffer using C-q C-g - after making sure there is no C-g char in the buffer.)

1
  • @Abigail: Yes, of course. Use a string that has no chars used anywhere. Updated to make that clear. Thx.
    – Drew
    Jan 17, 2019 at 22:33

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.