如何使用在vim中每行开头的1开始的运行数替换子匹配

时间:2012-11-11 16:33:35

标签: regex vim

我想用一个字符串替换每个子匹配,该字符串的递增索引从每行开头的1开始,以便替换字符串为varargin{1}varargin{2},{ {1}} ...对于更大的数字,数字字符串自然需要超过1个字符,例如:... varargin{3}varargin{9} ...输入数据是MATLAB代码,示例输入期望的产出如下。我主要是寻找varargin{10}解决方案,但其他方法也很受欢迎。

下面的正则表达式创建从vim开始的运行索引,但这些索引仅针对每一行进行更改。

1

我的问题是:

如何在每行的开头将索引重置为1,并在每个子匹配之间将索引递增1?

上面的代码是http://vim.wikia.com/wiki/Substitute_with_incrementing_numbers上显示的“替代升序号”示例的修改版本:

:let @a=1 | %s/\v.*'\zs.*\ze\);/\=substitute(submatch(0), '\s[a-zA-Z0-9{}_.]*', ' varargin{'.(@a+setreg('a',@a+1)).'}', 'g')/g

示例输入#1:

:let @a=1 | %s/abc/\='xyz_'.(@a+setreg('a',@a+1))/g

所需输出,例如输入#1:

messages.msg1.English = xprintf('analysis directory is on %s\n', analysis_dir);

示例输入#2:

messages.msg1.English = xprintf('analysis directory is on %s\n', varargin{1});

输入#2的所需输出:

messages.msg15.English = xprintf('the following sessions (%d pcs) have been approved: %s', handling_struct.n_of_accepted, handling_struct.accepted_sessions_vector);

示例输入#3:

messages.msg15.English = xprintf('the following sessions (%d pcs) have been approved: %s', varargin{1}, varargin{2});

输入#3的所需输出:

messages.msg19.English = xprintf('looking for files ''%s'' in %d separate dirs', give_file_struct.regex, number_of_dirs);

2 个答案:

答案 0 :(得分:4)

在这种情况下,我会使用以下命令。

:g/^/let n=[0] | s/abc/\='xyz_'.map(n,'v:val+1')[0]/g

答案 1 :(得分:1)

这可能是一个hacky解决方案,但如果我想在没有功能的情况下快速完成这项工作,那么我会做这样的事情:

:let i=1<cr>                                         "set the index variable
qbf lcEvarargin{<C-r>=i<cr>},<esc>:let i+=1<cr>q     "record a macro
u                                                    "undo those changes
:%norm$F':let i=1<C-v><C-j>1000@b<cr>                "run the macro on each line
:%s/,$/);/<cr>                                       "clean up

请注意,我使用vim中的<>表示法来表示特殊键,因此<cr>表示回车,<C-r>表示CTRL-R(请参阅:h i_CTRL-R)。 <C-v><C-j>在命令行中输入文字^@字符。这允许正常模式“按下回车”而不完成命令。我在这里使用:norm而不是宏,因为当:norm抛出错误时它只会移动到下一行。当宏抛出错误时(例如,当行中没有任何t时尝试执行ft)那么它就完全失败了。通过这种方式,我可以运行1000次宏,并在失败后继续运行。同样,可能不是最优雅的解决方案,但它有效,我的懒惰通常会胜出。