Vim 用不同的字符串替换每行

Vim Replace On Each Line With Different String

我从客户那里得到一份文档,其中有一个 GIANT table,看起来像这样:

<table id="someid">
<tr>
    <td>Product</td>
    <td class="product1">Product 1</td>
    <td class="product2">Product 2</td>
    <td class="product3">Product 3</td>
    <td class="product4">Product 4</td>
    <td class="product5">Product 5</td>
</tr>
<tr>
    <td>Boiling Point</td>
    <td>72</td>
    <td>91</td>
    <td>38</td>
    <td>21</td>
    <td>41</td>
</tr>
[ 45 more rows here]
</table>

实际上只有 15 种产品,而不是“product1”和“product2”,它们将产品的实际名称作为其先前存在的 classes。

客户要求我将 classes 添加到每个适当的 td 元素中,以便它们与他们的产品相匹配,例如 class="product1" 添加到每个第二个 td 中每一行。

一切都是静态的...我想知道 vim 中是否有快速的方法来做到这一点?是否可以告诉vim在每18行的某个位置添加一个字符串?还是我手动添加了所有 classes?

假设你的class名字和行号之间的关系可以描述为一个表达式,你可以使用:[range]substitutes/\=来用任何表达式替换行。例如,

1,10s/<td/\=submatch(0) . ' class="product' . (line('.') % 5 - 1) . '"'

会改变

<tr>
  <td></td>
  <td></td>
  <td></td>
</tr>
<tr>
  <td></td>
  <td></td>
  <td></td>
</tr>

<tr>
  <td class="product1"></td>
  <td class="product2"></td>
  <td class="product3"></td>
</tr>
<tr>
  <td class="product1"></td>
  <td class="product2"></td>
  <td class="product3"></td>
</tr>

您可以调整上述命令中的参数以满足您的需要。


对于复杂的替换,可以在临时vim文件中定义辅助函数,例如foo.vim

function! GetClassName()
  let order = line('.') % 5

  if order == 1
    return 'a'
  endif

  if order == 2
    return 'b'
  endif
endfunction

然后通过 :source % 获取它。

接下来,您可以切换到您的文件并按如下方式使用它

1,10s/^\s\+<td/\=submatch(0) . ' class="' . GetClassName() . '"'