2013-04-03 30 views
2

假設我有5行文本,如果我輸入一些命令讓vim處理每一行,Vim將逐一處理文本,第一行,第二行......最後一行。我想要的是讓Vim按相反的順序處理我的文本。那是最後一行,然後是第四行,最後是第一行。如何讓Vim處理我的命令後退?

爲什麼我需要這個? 我有以下文本

1234567890 
abc 
123 
def 
1234567890 
123456789 

欲從含有3個字符的行刪除換行符符號(\ n)的。這樣處理後,我會得到下面的文本

1234567890 
abc123def1234567890 
123456789 

這似乎是小菜一碟,我用下面的命令

:%s/\v(^\w{3})\n/\1/ 

,但我得到的是

1234567890 
abc123 
def1234567890 
1234567890 

爲什麼?我猜vim首先從第二行刪除\ n,然後這行有文本abc123,現在vim不會在123之後刪除\ n,因爲它現在不是3個字符,所以vim處理下一行def,並從中刪除\ n ,那是我得到的結果。

如果vim可以從後到前處理,這不會發生,我可以得到我想要的結果。

順便說一句,我可以通過其他方式得到預期的結果,我只想知道這是否可能。

回答

2

明確循環通過線(例如視覺選定的)的範圍內倒退,然後在每行執行該命令。我用:join這裏,而不是:substitute以換行符:

:for i in range(line("'>"), line("'<"), -1)| silent execute i . 'g/^\w\{3}$/join!' | endfor 
+0

這適用於gVim,但不適用於Vim – zdd

+1

嗯?我沒有看到任何會阻止在Vim中成功使用的東西。 –

2

可以用perl來實現:

while (<>) { 
    chomp if (/^...$/); 
    print; 
} 
+0

我不想使用Perl,只是Vim。 – zdd

1

在這種情況下,它更容易使用的:global命令加入線條。

:g/^\w\{3}$/normal! gJ 

命令gJ將當前行連接到下一行而不插入任何空格。上面的全局命令在每行僅包含三個字符時調用gJ。它通過在執行操作之前首先標記所有匹配來工作,因此避免了循環的問題。

+0

這不起作用,它會得到與我的命令相同的結果。 – zdd

1

此行應該做你想要什麼:

:%s/\v(\_^\w{3}\n)+/\=substitute(submatch(0),"\n","","g")/ 

,如果你想這樣做簡單的外部命令,例如awk,你可以:

%!awk '{printf "\%s", length($0)==3? $0:$0"\n"}' 
相關問題