我有很大的 XML 文件
<obj param="2542">
<obj param="2333">
<obj param="6433">
我需要将所有“param”值增加某个数字。我可以在很多编辑器中使用正则表达式搜索匹配我需要的数字,但是如何将一些数学运算应用到替换中呢?
答案1
经过一番探索,我发现 vim 只需一个命令就可以完成此操作,无需编写脚本。例如,要将以下所有数字加 50,<obj param="
您可以使用:
:%s@<obj param="\(\d\+\)@\='<obj param="' . (submatch(1) + 50)@g
让我来分析一下。
:
是在 vim 中进入/表示命令行模式的一般方法。
%
意味着在整个文档范围内;您可以输入一个数字范围,例如,1,50
只在前 50 行内执行此操作。
s
是 substitute 的简写(如果你愿意,你可以把整个单词写出来)
@
是分隔符;您可以使用任何其他字符,只要它不在您要搜索的内容中即可。只需使用三次即可。(语法类似于sed
.)
直到下一个分隔符 @ 出现为止的所有内容都是要搜索的正则表达式模式,在本例中,<obj param="
后面跟着\d\+
,即任意数量的数字。\(
和\)
用于将整个数字序列设置为单个正则表达式组,该组将匹配反向引用\1
,例如 或 vim 的submatch
命令。
然后定界符标记@
后面的内容为替换文本。
这里开头的意思\=
是替换某些求值表达式的结果,而不是正则表达式模式或字符串,这才是关键。
然后我们有'<obj param="'
替换文本的开头。.
接下来是 vim 的连接字符串函数。
submatch(1)
是 vim 内置函数,它只能在替换命令中使用,并返回与正则表达式相同的字符串\1
;您可以将submatch(2)
其用作正则表达式的等价物\2
。 (\0
是整个匹配的模式,但我们在这里不需要它。)搜索模式中的\(
和\)
用于标记什么算作submatch(1)
。
因此,结果等于将搜索模式(submatch(1) + 50)
后面的数字加上 50 。<obj param="
分隔符@
再次用于标记替换文本的结束。
该标志g
用于使替换全局化;如果您只想替换每行上的第一个实例,则可以省略此项。
您大概可以从那里算出如何对不同的数字进行加、减、除等等。
答案2
在 Emacs (自版本 23 起) 中:用于\,
执行任意 Lisp 代码正则表达式替换例如,要计算数字的平方,可以使用
M-x replace-regexp
param="\([0-9]+\)"
param="\,(* \#1 \#1)"
在 Vim 中:用 开始替换文本\=
(参见:help sub-replace-special
)。例如,要计算数字的平方:
s!param="\([0-9]\+\)"!\='param="'.submatch(1)*submatch(1).'"'!
有几种编辑器允许您使用宏来做这类事情:定义一个宏,1. 查找下一个匹配项,2. 执行替换(必要时使用外部算术工具);只要有匹配项,就重复执行该宏多次。
答案3
你可以使用 vim 来帮你完成这个。只需打开你的文件并录制宏. 例如:搜索任意号码
/[0-9]{1,}
然后按 q 和 a(将宏存储在寄存器 a 中)。之后,按 Ctrl-X(将数字增加 1),然后按 n(获取下一个搜索结果)。完成后,再次按 q 保存宏。现在,您可以通过按 @+a 将宏应用于下一个数字。这将更改当前数字并跳转到下一个数字。通过重复该操作或使用 x@a,您可以重复该操作 x 次。
好吧,这个描述可能不足以说明如何做到这一点。只需参考描述 vim 中的宏机制的教程即可。