質問

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