Vim/sed/awk如何使用递增整数进行查找和替换

4

我有一个包含像 [this][],[that][],... 和 [the other][] 这样的单词的 Markdown 文件。我知道如何在 MacVim 中找到这些单词,但是如何将它们替换为 [this][1]、[that][2]、... 和 [the other][n],其中 n 在我的情况下为 26 呢?

如果使用 sed、awk 或甚至 Ruby 比使用 MacVim 更简单,我也接受这些解决方案。

6个回答

6
perl -p -i -e 's/(\[.*?\])\[\]/"$1\[".(++$i)."]"/ge' /path/to/file

Vim:

:let g:lastcount=0
:function PlusPlus()
  let g:lastcount+=1
  return g:lastcount
  endfunction
:%g/./s/\V[\.\{-}][\zs\ze]/\=PlusPlus()/g

2
ruby -p -e \
'begin t=$_.clone; $_.sub! "][]", "][#{@n=@n.to_i+1}]";end until t==$_' \
  < somefile

或者,对于原地编辑文件的版本:
ruby -i.tmp -p -e \
'begin t = $_.clone; $_.sub! "][]", "][#{@n=@n.to_i+1}]"; end until t == $_' \
somefile

2

好的,用Vim编写此解决方案是完全可能的。我已经使用Incrementor对象一段时间来处理这些事情:

---8<--- vim代码

function! Incrementor(start, step)
  let incrementor = {}
  let incrementor.initial_value = a:start
  let incrementor.value = incrementor.initial_value
  let incrementor.step = a:step
  function incrementor.val() dict
    return self.value
  endfunction
  function incrementor.next() dict
    let self.value += self.step
    return self.value
  endfunction
  function incrementor.reset() dict
    let self.value = self.initial_value
    return self.value
  endfunction
  return incrementor
endfunction

" With the Incrementor function above saved in, say,
" ~/.vim/plugin/incrementor.vim, you can then create incrementors as you need
" them and use them in substitutions, like this:

let inc = Incrementor(0,1)
28,$s/\v\[(\w+)\]\[\]/\="[".submatch(1)."][".inc.next()."]"/

finish

" test case

foo
[this][]
[that][]
[theother][]
bar

将整个代码示例复制到文件中,直到结尾处的“bar”,然后保存并在Vim中执行:so%以进行测试。请保留HTML标记。

1

如果你只需要做一次,以后再也不用做了,那么在编辑器中完成是可以的。但当你需要重复执行时,手动操作就会变得非常痛苦,这时就需要自动化来解决问题。

没有包含目标文本样本的情况下,就像在黑暗中射击一样,但是使用 Ruby 似乎接近于你的描述:

text = %{
[Lorem][] ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut
labore [et][] dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi [ut][] aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse [cillum][] dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat
non proident, sunt in culpa qui [officia deserunt][] mollit anim id est laborum.
}

text.scan(/\[[^\]]+\]\[\]/).each_with_index{ |t, i| text[t] = t.sub('[]', "[#{1 + i}]") }
puts text

# >> 
# >> [Lorem][1] ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut
# >> labore [et][2] dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
# >> laboris nisi [ut][3] aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
# >> voluptate velit esse [cillum][4] dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat
# >> non proident, sunt in culpa qui [officia deserunt][5] mollit anim id est laborum.

如果你想要自动化在vim中的操作,你只需要编写一个映射(或者对于更复杂的任务,编写一个脚本)。这里没有任何痛苦,这就是为什么许多程序员喜欢vim的原因。 - ZyX
顺便说一下,如果你在vim中这样做,你将能够轻松撤消操作(使用持久性撤消:即使你已经退出编辑器)。 - ZyX
我在工作和家中99%的编辑工作都使用vim/gvim/macvim,但我仍然不会尝试将其用作自动化工具。 - the Tin Man

1

试一试这个:

awk 'BEGIN{c=1}{for(w=1;w<=NF;w++){s=sub("\\[\\]","["c"]",$w);if(s)c++};print}' inputfile

小建議:awk 'BEGIN {c=1} {for(w=1;w<=NF;w++){c+=sub("\[\]","["c"]",$w)};print}' - Beta
@Beta:谢谢。我忽略了那个。 - Dennis Williamson

0
你可以通过使用几个 Vim 命令和宏来轻松完成这个任务:
/\[\]<cr>a1<esc>qqyi[np<C-a>q25@q

那就是查找字符串"[]",为第一个括号添加数字1。然后开始录制宏。复制括号内的所有内容,转到下一个匹配项并粘贴。然后递增数字。停止录制然后根据需要重复执行宏。每次执行都会递增插入的数字。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接