4

使用vim,我正在尝试转换以下两行

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

进入

abcd
efgh

我正在使用正则表达式,

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

但是,我得到的输出是,

[1:0]abcd,
efgh,

感谢任何帮助!谢谢。

4

6 回答 6

4

:help pattern给出了原因(尽管从先前接触到不同的可能性中猜测出原因有很大帮助:-)

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 的正则表达式匹配器是一个首次匹配引擎。POSIX 要求最左最长。纯粹主义者可能会争辩说,其他任何东西都不是正则表达式匹配器,而只是一个“模式匹配器”,这可能与 vim 称它们为“模式”有关...... sed并且perl是最左边最长的:

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

但是对于首场比赛的引擎,您必须做一些不同的事情。重新排序您的替代品,它的工作原理:

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

替换\s*\s+使其对订单不敏感:

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

Vim 的g标志似乎只替换第一个匹配分支的每次出现,然后重试,直到没有任何变化。

只是为了完整和混乱,

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

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

考虑到上面推断的规则,这对我来说实际上是有意义的。

(编辑:gawksgensubnvisextended引擎显然也是最左边最长的)

于 2013-06-04T18:14:09.940 回答
3

尝试这个

\v\[.*]\s+|output\s+|reg\s+
于 2013-06-04T10:51:03.950 回答
3
$xbd0

将在一条线上完成这项工作。您可以录制一个宏以自动在多行上执行此操作。

于 2013-06-04T11:09:08.907 回答
1

您的正则表达式中的问题是您要求 \s* 的部分。这意味着字面意思是“没有或很多空格”。由于整个正则表达式是一个大 OR,那么 Vim 将开始使用你的字符串,直到找到至少一个空格。发生这种情况时,它将再次从 OR 的开头开始匹配并重复该过程。因此,这意味着您在 \s* 之后尝试接收的任何表达式都将被忽略,因为 \s* 可以消耗尽可能多的内容,直到找到空白字符为止。要验证这一点,请注意,如果您更改 \s* 的位置,您将得到不同的结果,这意味着仅删除 \s* 之前的表达式。

我相信你真正想要的正则表达式是:

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

表示您要替换至少有空格的地方。这对我来说很好。

于 2013-06-04T13:53:30.603 回答
1

您的正则表达式不起作用的原因。

似乎 vim 从左到右读取正则表达式并尝试按顺序匹配联合的每个部分。

所以永远不会到达output|reg|\s*|\[.*\]|,\[.*\]因为空字符串匹配\s*每个字符之间的字符串。由于 vim 正则表达式引擎匹配了某些内容,因此它会立即进行替换。

如果您只是重新排序\s*最后的联合,则正则表达式按预期工作。

所以命令应该是:%s/\voutput|reg|\[.*\]|,|\s*//g

于 2013-06-04T13:55:38.523 回答
0

这有效(在结尾处寻找 4 个字母):

%s/^.*\<\(\a\{4}\),\s*$/\1/g
于 2013-06-04T12:09:58.460 回答