vim 用数学表达式替换

vim substitution with mathematical expression

我需要替换以下行:

[rescap] l=1.2u w=1.5u 

来自

[rescap] l=1.2u w=1.5u r=0.8k

r 0.8k 的值为 l/w

我正在尝试 vim(已经在 perl 中完成但想使用 vim 实现)

:s/l=\(.\*\)u w=\(.\*\)u/l=u w=u r=*k/

但它不计算表达式并打印:

[rescap] l=1.2u w=1.5u r=1.2*1.5k

如果我尝试 \= 计算表达式,它假定 l 和 w 为变量并抛出错误。

:s/l=\(.\*\)u w=\(.\*\)u/\=l=u w=u r=*/    

我必须 运行 以上表达式使用 vim -s scriptfile 通过许多文件。 只需要弄清楚上面的替换语句即可。

您正在寻找:

%s#\vl\=([0-9.]+)u\s+w\=([0-9.]+)u\zs.*#\=' r='.string(eval(submatch(1))/eval(submatch(2))).'u'

重要的事情是:

  • \= 告诉你将插入一个表达式——第三个(前两个是我使用带有 \v 的非常神奇的正则表达式引起的怪癖)-> :h :s\=
  • submatch() 访问 </code> 和 <code>
  • eval() 将子匹配转换为浮点数,string() 将其转换回来
  • 另请注意,为了在 \= 之后插入文本,您需要显式构建一个字符串

然后,我用过:

  • \v 简化正则表达式,
  • :s# 而不是 :s/ 来简化 替换 表达式,因为我需要 / 来计算除法,
  • \zs 以简化 替换 表达式。

最后需要了解一条信息,以获取与 regex/pattern 相关的文档,在您要查找的内容前加上斜杠 -> :h /\v:h /\zs

以下命令也有效:

s#\vl\=(\d+\.\d+)u w\=(\d+\.\d+)u#\=printf('%s r=%.1fk', submatch(0), str2float(submatch(1))/str2float(submatch(2)))  

一些解释:

  • submatch(0) 将包含所有匹配的字符串
  • str2float()用于将string转为float类型
  • printf() 用于方便控制输出字符串格式。