2

这是这个问题的扩展(我之前问过):

如何删除每隔一行,并在选择后粘贴已删除的结果?

,但现在我想推广到 n-striped 数据

因此,这个问题的扩展将是——如何将其推广到非条带化数据集?

显然,上面的内容实际上是每隔一行进行 2 行去条带化,但是如果我们想有效地将​​下面这种模式中的数据排序为 3 行去条带呢?N行条纹?

前:

111
222
333
444
555
666

之后的新功能(如果使用 2 条纹):

111
333
555
222
444
666

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

111
444
222
555
333
666

可能有一个算法名称;我在排序方面没有很强的背景,但它可能有一个名字——如果有人能澄清,请告诉我。

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

所以我会为脚本设计的东西类似于(在数据上进行视觉线选择),然后调用一个用户宏函数,如

:'<','>' call Destripe(2)
:'<','>' call Destripe(3)

其中唯一的参数描述了条带化。

如果我有 3 条数据,另一个例子(为了更清楚地说明我想要做什么)

之前(左)和之后(右):

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

带有 2 条数据的示例

之前(左)和之后(右):

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

感谢@lornix 的想法

4

3 回答 3

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 和更高版本可能不会产生您要查找的内容,因为您没有指定从文件的当前(移位)内容或文件的原始内容中读取。(这有意义吗?)

如所写,它需要提供一个范围,'%' 或 '<,'> 或 line #'s。

于 2012-07-10T11:14:53.547 回答
2

老实说,如果这不是经常做的事情,或者如果没有太多的条纹,我只需在命令行中输入以下内容(三个条纹)。也许你可以看到这是如何概括的。

:let @a = '' | let @b = ''
:g/^/ +d A | d B
:put a | put b
于 2012-07-12T11:03:40.597 回答
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) & AFTER (RHS):

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

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

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

于 2012-07-11T15:27:54.473 回答