0

I have the following line:

#ifdef DCC_3D_HPP || DCC_2D_HPP

I want to replace it with:

#if defined(DCC_3D_HPP) || defined(DCC_2D_HPP)

I use the following prompt with replace-regexp:

#ifdef \([A-Z0-9_]+\) \|\| \([A-Z0-9_]+\) → #if defined(\1) || defined(\2)

When I do that, I get the following strange result:

#if defined(DCC_3D_HPP) || defined()|#if defined() || defined()|#if defined() || defined() #if defined() || defined()D#if defined() || defined()C#if defined() || defined()C#if defined() || defined()_#if defined() || defined()2#if defined() || defined()D#if defined() || defined()_#if defined() || defined()H#if defined() || defined()P#if defined() || defined()P#if defined() || defined()

I'm not sure why this happens, nor how to debug it. I have an idea that this has something to do with the fact that consecutive replacements also constitute matches for my expression, and that's probably the culprit.

My question is, how do I get it to do exactly what I want, and is there a way to debug these kinds of expressions to see what goes wrong? For example, replace only once, then see what happened? Thank you.

EDIT: Running query-regex-replace shows that, for whatever reason, the expression I gave matches the first portion of what I need replaced, i.e. #ifdef DCC_3D_HPP, and then replaces that only. I have no idea why it does this. It also seems to match empty lines before the necessary lines. I feel like I completely misunderstand something here.

5
  • as @shynur mention you've got two logical OR's, not two escaped pipe characters. try [|][|] or [|]\{2\} instead
    – nega
    Jul 19, 2023 at 17:58
  • 1
    You might find re-builder helpful when constructing regexps: do M-x re-builder in the above buffer (best to have it in a single window in the frame) and type you regexp; it will show you what is matched at every stage.
    – NickD
    Jul 19, 2023 at 19:40
  • 2
    @nega: Or far more sanely: ||
    – phils
    Jul 19, 2023 at 22:12
  • @phils force of habit from my backslash-phobia :) speaking of which @nickd neglected to mention that you need to do C-c TAB string RET in re-buildier to select the "replace-regex" style of regexes, otherwise you'll have to translate multiple blackslashes yourself
    – nega
    Jul 19, 2023 at 22:45
  • Indeed; emacs.stackexchange.com/q/5568/454 may also be useful reading on that point.
    – phils
    Jul 20, 2023 at 0:10

1 Answer 1

2

I use the following prompt with replace-regexp:

#ifdef \([A-Z0-9_]+\) \|\| \([A-Z0-9_]+\) → #if defined(\1) || defined(\2)

\| means logic OR, which is not what you want. (See 35.3.1.3 Backslash Constructs in Regular Expressions.) I'm not sure whether this is also true in most regexp implementations (e.g., Perl, egrep, ...), but if so, this question is about regexp instead of Emacs and thus doesn't belong to Emacs.SE.

My question is, ... is there a way to debug these kinds of expressions to see what goes wrong? For example, replace only once, then see what happened?

Replace once, then undo. It shall be enough.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.