6

在 VIM 宏中,条件操作是如何处理的?

 if condition is true
       do this
 else
       do something else

基本示例

文件内容:

_
abcdefg

宏将执行以下操作:

G^
if letter is one of the following letters: a e i o u
   gg$i0<ESC>
else
   gg$i1<ESC>
Gx

重复 7 次缓冲区将是:

_0111011

那么,如何验证条件是否为真然后运行操作?

4

2 回答 2

8

由于 Vim 中没有“条件”命令,因此不能严格使用宏来完成。您只能使用这样一个事实,即当宏中的命令发出哔哔声时,宏重放被中止。递归宏使用这个事实来停止迭代(例如,当j命令不能移动到缓冲区末尾的下一行时)。

另一方面,条件逻辑在 Vimscript 中非常简单,宏可以:call轻松实现任何 Vimscript 功能。

您的示例可以这样表述:

function! Macro()
    " Get current letter.
    normal! yl
    if @" =~# '[aeiou]'
        execute "normal! gg$i0\<ESC>"
    else
        execute "normal! gg$i1\<ESC>"
    endif
endfunction
于 2014-06-06T18:31:34.580 回答
3

一种解决方案是采用更实用(而不是命令式)的方法,例如这个特定任务(和许多其他任务)可以通过替换来完成:

G:s/\v([aeiou])|./\=strlen(submatch(1)) ? 1 : 0/g<CR>gggJ

IE:

G  " go to the first non-blank character on the last line

" replace each vowel with 1 and everything else with 0
:s/\v([aeiou])|./\=strlen(submatch(1)) ? 1 : 0/g<CR>

gg " go to the first line
gJ " and append the line below

根据任务的不同,您可能会发现插件(例如abolish.vim)以比放入 vimscript 更方便的方式打包逻辑。

另一种方法是按照此处:global所述使用,再次将任何附加逻辑移动到方便/必要的命令中。如果要处理的文本尚未采用正确的格式(基于行),则可以将其拆分为行,使用 进行操作,然后重新组合/恢复。:g:g

您还可以将一系列不重叠的命令与|( :help :bar) 捆绑在一起以近似if/else链,例如转换:

DMY: 09/10/2011 to 10/11/2012
DMY: 13/12/2011
MDY: 10/09/2011 to 11/10/2012
MDY: 12/13/2011

到:

DMY: 2011-10-09 to 2012-11-10
DMY: 2011-12-13
MDY: 2011-10-09 to 2012-11-10
MDY: 2011-12-13

为清晰起见进行了格式化(有关:execute用法,请参见此处):

:exe 'g/^DMY:/s/\v(\d\d)\D(\d\d)\D(\d{4})/\3-\2-\1/g' |
      g/^MDY:/s/\v(\d\d)\D(\d\d)\D(\d{4})/\3-\1-\2/g
于 2014-08-08T20:29:44.643 回答