使用vim,我正在尝试转换以下两行
output reg [1:0] abcd,
output reg efgh,
进入
abcd
efgh
我正在使用正则表达式,
:%s/\voutput|reg|\s*|\[.*\]|,//g
但是,我得到的输出是,
[1:0]abcd,
efgh,
感谢任何帮助!谢谢。
: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
考虑到上面推断的规则,这对我来说实际上是有意义的。
(编辑:gawk
sgensub
和nvi
sextended
引擎显然也是最左边最长的)
尝试这个
\v\[.*]\s+|output\s+|reg\s+
$xbd0
将在一条线上完成这项工作。您可以录制一个宏以自动在多行上执行此操作。
您的正则表达式中的问题是您要求 \s* 的部分。这意味着字面意思是“没有或很多空格”。由于整个正则表达式是一个大 OR,那么 Vim 将开始使用你的字符串,直到找到至少一个空格。发生这种情况时,它将再次从 OR 的开头开始匹配并重复该过程。因此,这意味着您在 \s* 之后尝试接收的任何表达式都将被忽略,因为 \s* 可以消耗尽可能多的内容,直到找到空白字符为止。要验证这一点,请注意,如果您更改 \s* 的位置,您将得到不同的结果,这意味着仅删除 \s* 之前的表达式。
我相信你真正想要的正则表达式是:
:%s/\voutput|reg|\s+|\[.*\]|,//g
表示您要替换至少有空格的地方。这对我来说很好。
您的正则表达式不起作用的原因。
似乎 vim 从左到右读取正则表达式并尝试按顺序匹配联合的每个部分。
所以永远不会到达output|reg|\s*|\[.*\]|,
,\[.*\]
因为空字符串匹配\s*
每个字符之间的字符串。由于 vim 正则表达式引擎匹配了某些内容,因此它会立即进行替换。
如果您只是重新排序\s*
最后的联合,则正则表达式按预期工作。
所以命令应该是:%s/\voutput|reg|\[.*\]|,|\s*//g
这有效(在结尾处寻找 4 个字母):
%s/^.*\<\(\a\{4}\),\s*$/\1/g