vim中行条带数据的有效排序宏是什么?

时间:2012-07-10 05:06:17

标签: vim

这是这个问题的延伸(我之前曾问过):

How to delete every other row, plus paste deleted results after selection?

,但现在我想推广到n条纹数据

因此,这个问题的扩展将是如何将此概括为无条带数据集?

显然,上面的内容实际上是每排其他行的2行,但是如果我们想要在下面这种模式中有效地对数据进行排序,那么对于3行的排序是什么? N排destripe?

在:

111
222
333
444
555
666

NEW AFTER(如果使用2条纹):

111
333
555
222
444
666

NEW AFTER(3条纹如下图所示):

111
444
222
555
333
666

可能有一个算法名称;我没有强大的分类背景,但可能有一个名字 - 如果有人可以澄清请通知我。

同样,带参数的宏(或不是)是我在这里尝试解决的问题。这在排序实用程序空间中也可能有效,但基于前一个问题的答案,我认为它在vimscript中是可行的。

那么我想为脚本制作的东西就像(在数据上做一个视觉线选择),然后调用像

这样的用户宏函数
:'<','>' call Destripe(2)
:'<','>' call Destripe(3)

其中单个参数描述了条带化。

另一个例子(我想要做的更清楚),如果我有3条数据

BEFORE(LHS)&amp;之后(RHS):

aaa        aaa
bbb        aaa
ccc        aaa
aaa        bbb
bbb        bbb
ccc        bbb
aaa        ccc
bbb        ccc
ccc        ccc

带有2条纹数据的示例

BEFORE(LHS)&amp;之后(RHS):

aaa        aaa
bbb        aaa
aaa        aaa
bbb        bbb
aaa        bbb
bbb        bbb

感谢@lornix的想法

3 个答案:

答案 0 :(得分:2)

"
function! Destripe(stripe) range
    call setpos('.',[0,a:firstline,1,0])
    let numlines=(a:lastline-a:firstline+1)/a:stripe
    let currentline=a:firstline+a:stripe-1
    while numlines > 0
        call setpos('.',[0,currentline,1,0])
        let currentline=currentline+a:stripe-1
        silent :.m$
        let numlines=numlines-1
    endwhile
endfunction
"
%call Destripe(2)

在111,222,333 ...行列表中获取上述内容,给出以下内容:(加倍以节省空间)

111    111
222    333
333    555
444    777
555    999
666    222
777    444
888    666
999    888

我担心3及更高版本可能无法生成您正在寻找的内容,因为您没有指定从文件的CURRENT(移位)内容或文件的ORIGINAL内容中读取内容。 (这有意义吗?)

如上所述,它需要提供一个范围,'%'或'&lt;,'&gt;或行#。

答案 1 :(得分:2)

说实话,如果这不是必须要做的事情 经常,或者如果没有太多的条纹, 我只需在命令行键入以下内容 (三条纹)。也许你可以看到这是怎么回事 可以概括。

:let @a = '' | let @b = ''
:g/^/ +d A | d B
:put a | put b

答案 2 :(得分:0)

function! Destripe(stripe) range

let s:rowbeg=getpos("'<")[1]           
let s:rowend=getpos("'>")[1]           
let s:curSetLngth=s:rowend-s:rowbeg+1

let stripe=a:stripe
let s:rowend += 1            

while stripe >= 2

  let stripeMin1 = stripe - 1                 

  " clear register
  let @e=''                                   

  " delete last stripe and append
  " to the e register
  execute "let @a='".stripeMin1."j\"Edd'"     

  " count how many times to perform a-macro
  let s:stripesInSlctn = s:curSetLngth / stripe           

  "silent ":'<" 
  let s:count=0
  while s:count <= s:stripesInSlctn
    norm @a 
    let s:count = s:count + 1
    "dbg echo s:count s:stripesInSlctn s:curSetLngth stripe s:rowbeg s:rowend
  endwhile

  let s:curSetLngth -= s:stripesInSlctn + 1

  " rowend location
  let s:rowend -= s:count      
  execute s:rowend

  " e-register collected the stripes
  " so place at bottom of selection
  norm "ep
  execute s:rowbeg
  let stripe -= 1
  let s:stripesInSlctn -= 1
endwhile

endfunction

如果有办法清理它,请告诉我;例如,它仅适用于视觉线选择,因为我设置了脚本。

要从命令行调用,请选择可视行,然后

:'<,'> call Destripe(n)

其中n是条纹数。

脚本有效执行以下操作 BEFORE(LHS)&amp;之后(RHS):

aaa        aaa
bbb        aaa
ccc        aaa
aaa
bbb        bbb
ccc        bbb
aaa        bbb
bbb 
ccc        ccc
           ccc
           ccc

解决方案的一个潜在问题是,耗尽结果之间的空白区域始终存在。有人会知道如何调试那个吗?在大多数情况下,这可以完成工作。感谢@lornix的一些灵感(我甚至不知道如何在vim中编写脚本!,我也不知道如何将范围输入函数)。 SO社区如果您对如何改进它有任何意见我会非常感激。

另一个需要考虑的问题是,norm命令可能根本无法使用,因为它在“每一行”的基础上工作,而不是在第n行的基础上工作!所以基本上我希望有一种方法可以在第n行进行操作(在我这里的乘法场景中很有用,或者你对每3行,每4行感兴趣的情况等)也许有一个特点我只是不使用?