在VimGolf挑战“使用Vim进行简单文本编辑”:#1解决方案如何运作?

时间:2011-07-13 13:07:35

标签: vim

使用Vim进行简单的文本编辑: http://vimgolf.com/challenges/4d1a34ccfa85f32065000004

我发现很难理解#1解决方案(得分13)。

很抱歉,此帖子中没有解决方法,因为我不知道是否适合这样做。

1 个答案:

答案 0 :(得分:41)

解决方案以:g命令为中心。来自帮助:

                                             :g   :global   E147   E148 
:[range]g[lobal]/{pattern}/[cmd]
                        Execute the Ex command [cmd] (default ":p") on the
                        lines within [range] where {pattern} matches.

基本上,解决方案在具有“V”的行上执行一些ex命令, 这正是那些需要编辑的。你可能已经注意到了 早期的解决方案依赖于复制线,而不是真正改变 他们。该解决方案特别显示了一个有趣的模式:

3jYjVp3jYjVp3jYjVpZZ
^     ^     ^

使用宏可以减少:

qa3jYjVpq3@aZZ

使用:g命令的解决方案基本上做同样的事情。首先 执行的命令是t.。来自帮助:

                                                         :t 
:t                  Synonym for copy.

:[range]co[py] {address}                             :co   :copy 
                        Copy the lines given by [range] to below the line
                        given by {address}.

给出的地址是.,表示当前行:

Line numbers may be specified with:          :range   E14   {address} 
        {number}            an absolute line number
        .                   the current line                           :. 
        $                   the last line in the file                  :$ 
        %                   equal to 1,$ (the entire file)             :% 
        't                  position of mark t (lowercase)             :' 
        'T                  position of mark T (uppercase); when the mark is in
                            another file it cannot be used in a range
        /{pattern}[/]       the next line where {pattern} matches      :/ 
        ?{pattern}[?]       the previous line where {pattern} matches  :? 
        \/                  the next line where the previously used search
                            pattern matches
        \?                  the previous line where the previously used search
                            pattern matches
        \&                  the next line where the previously used substitute
                            pattern matches

因此ex命令t.表示“将当前行复制到当前行下面”。 然后,有一个栏:

                                                     :bar   :\bar 
'|' can be used to separate commands, so you can give multiple commands in one
line.  If you want to use '|' in an argument, precede it with '\'.

d命令,显然删除了该行。给了它一系列的 +,表示“当前行+ 1”。您可以简称.+1,但+。 可以围绕:range的帮助阅读这些信息:

The default line specifier for most commands is the cursor position, but the
commands ":write" and ":global" have the whole file (1,$) as default.

Each may be followed (several times) by '+' or '-' and an optional number.
This number is added or subtracted from the preceding line number.  If the
number is omitted, 1 is used.

就是这样。

:g/V/t.|+d<CR>ZZ
  

在每个有“V”的行上,将其复制并删除下一行。写   并退出。


我没有提到的一件事是为什么:g命令被执行三次而不是6次甚至更多次(沿着进程重复行)。 :g命令开始将光标定位在第一行,然后下移到$。但是如果命令改变当前行,:g将从那里继续。所以:

:g/V/

当前行是4.现在:

t.

这会将光标移动到第5行。然后:

+d

删除第6行,光标保持在5.所以下一个:g匹配将在第8行。