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.

Drew
  • 75,699
  • 9
  • 109
  • 225
hrkrshnn
  • 439
  • 6
  • 14
  • 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 '19 at 04:25

3 Answers3

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.

NickD
  • 27,023
  • 3
  • 23
  • 42
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).

phils
  • 48,657
  • 3
  • 76
  • 115
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.)

Drew
  • 75,699
  • 9
  • 109
  • 225
  • @Abigail: Yes, of course. Use a string that has no chars used anywhere. Updated to make that clear. Thx. – Drew Jan 17 '19 at 22:33