سؤال

I am working on a C project an I want to change all bool-variable checking from

if(!a)

to

if(a == false)

in order to make the code easier to read(I want to do the same with while statements). Anyway I'm using the following regex, which searches for an exclamation mark followed by a lowercase character and for the last closing parenthesis on the line.

%s/\(.*\)!\([a-z]\)\(.*\))\([^)]+\)/\1\2\3 == false)\4/g

I'm sorry for asking you to look over it but i can't understand why it would fail.

Also, is there an easier way of solving this problem and of using vim regex in general?

هل كانت مفيدة؟

المحلول

One solution should be this one:

%s/\(.*\)(\(\s*\)!\(\w\+\))/\1(\3 == false)/gc

Here, we do the following:

%s/\(.*\)(\(\s*\)!\(\w\+\))/\1(\3 == false)/gc

   \--+-/|\--+--/|\---+--/|
      |  |   |   |    |   finally test for a single `)`.
      |  |   |   |    (\3): then for one or more word characters (the var name).
      |  |   |   the single `!`
      |  |   (\2): then for any amount of white space before the `!`
      |  the single `(`
      (\1): test for any characters before a single `(`

Then, it's replaced by the first, third pattern, and then appends the text == false, opening and closing the parentheses as needed.

نصائح أخرى

To do this in vim, you could use the following:

%s/\(if(\)!\([^)]\+\)/\1\2==false/c

  • make sure that only if(!var)-constructs are matched, you could change that to while for the next task
  • c asks for confirmation for every occurence

As @Kent said this is not a small undertaking. However for the simple case of just if(!a) it can be done.

:%s/\<if(\zs!\(\k\+\)\ze)/\1 == false/c

Explanation:

  • Start by making sure if is at a word bound by \<. This ensures it isn't part of some function name.
  • \zs and \ze set the start and end of the match respectively.
  • Capture the variable via the keyword class \k (\w works too) ending up with \(\k\+\)
  • For extra safety use the c flag to confirm each substation.

Thoughts:

  • This will need to be updated for other constructs, e.g. while
  • May need to make alterations for extra white-space, e.g. \<if\s*(\s*\zs!\(\k\+\)\ze\s*)
  • May want to use [a-z0-9_] instead of \k or \w to avoid capturing macros
  • There are instances where you may not have a construct: foo = !a && b;
  • This only handles the false cases. Doing a == true may be far trickier

Depending on your case it might be safest to just do the following:

:%s/!\([a-z0-9]\+\)/\1 == false/gc

On top of the answers already presented, I would say that the code does not smell like it needs refactoring. For a global regex replacement, the primary problem is to find

all bool-variables

and distinguish them from pointers, etc.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top