Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vim regex match with square brackets not working

Tags:

regex

vim

Using vim, I am trying to convert the following two lines

  output reg [1:0] abcd,
  output reg efgh,

into

abcd
efgh

I am using the regular expression,

:%s/\voutput|reg|\s*|\[.*\]|,//g

But, I am getting the output as,

[1:0]abcd,
efgh,

Appreciate any help! Thanks.

like image 712
Rakesh Avatar asked Dec 16 '22 10:12

Rakesh


2 Answers

:help pattern gives the reason (although it helps, a lot, to have guessed the reason from prior exposure to the different possibilities :-)

1. A pattern is one or more branches, separated by "\|". It matches anything that matches one of the branches. Example: "foo\|beep" matches "foo" and matches "beep".If more than one branch matches, the first one is used.

Vim's regex matcher is a first-match engine. POSIX mandates leftmost-longest. Purists might argue that anything else isn't a regex matcher at all, but only a "pattern matcher", which may have something to do with vim calling them "patterns" ... sed and perl are leftmost-longest:

$ sed -r 's/output|reg|\s*|\[.*\]|,//g' @@
abcd
efgh
$ perl -ple 's/output|reg|\s*|\[.*\]|,//g' @@
abcd
efgh

but with a first-match engine you have to do things a little differently. Reorder your alternatives, it works:

:%s/\voutput|reg|\[.*\]|,|\s*//g

And replacing \s* with \s+ makes it insensitive to order:

:%s/\voutput|reg|\s+|\[.*\]|,//g

Vim's g flag seems to replace every occurrence of just the first matching branch and then retry, until nothing changes.

Just to be complete and confusing,

:%s/\v(reg|output|\s*|\[.*\]|,)*//
abcd,
efgh,

and

:%s/\v(reg|output|\s*|\[.*\]|,)*//g
abcd
efgh

which for a brief moment actually made sense to me given the rules deduced above.

(edit: gawks gensub and nvis extended engine are also apparently leftmost-longest)

like image 96
jthill Avatar answered Dec 21 '22 11:12

jthill


try this

\v\[.*]\s+|output\s+|reg\s+
like image 32
i100 Avatar answered Dec 21 '22 11:12

i100