Vim:如何删除第二行?


Answers:


105

您可以为此使用宏。请执行下列操作。

  • 在命令模式下启动。
  • 通过按转到文件的开头 gg
  • qq
  • 单击向下箭头,然后按dd
  • q
  • 10000@q

PS:要进入命令模式,只需按Escape两次。


11
当然,假设您的文件长度少于20,000行:-)
paxdiablo 2009年

3
其实你是错的迈克尔。当VI到达文件末尾时,它将立即停止运行该宏,因此可以完美运行。您可以使用上面的示例轻松地进行尝试。

1
好吧,就像任何宏一样,您需要在第一时间将其正确设置,但是之后您只需键入10000 @ q就可以将其应用于任何文件。无论哪种方式,我都认为这只是口味问题,所以我绝对不会开始进行哲学辩论。:)

3
我更喜欢使用“宏”。使用宏,您可以“描述”如何解决一项特定任务,并让VIM为您重复执行。RUI,我希望使用'j'代替箭头键。
SolutionYogi

4
:g/^/+d来自用户stackoverflow.com/users/254635/ib(贝洛)的解决方案更为简洁。
SergioAraujo 2011年

256

一种精巧(高效)的方法可以:+delete使用以下:global命令在每行上调用以下命令来删除当前行之后的行:

:g/^/+d

10
为什么这个答案没有得到更多的赞成票?这是如此干净和简单。或者,您可以删除第一行并运行上面的命令以删除所有奇数行。
Usagi'3

3
@Usagi:谢谢!我对此也有同感。是的,您绝对正确,:1d|g/^/+d删除奇数行。
ib。

@Usagi在他的答案出现两年之前,另一个答案被选为“最佳答案”。另外,尽管这是一个更优雅的解决方案,但它可能是以更有用的方式编写的(即,没有提到^的作用,而任何人都可以轻松理解该宏)。
user1271772 2013年

3
抱歉,但是由于没有解释该命令如何执行所需的行为,因此我不赞成使用该命令,而是选择接受的答案,因为我了解该命令是如何实现目标的。给男人一条鱼和教他如何钓鱼是有区别的。
加布

3
我不知道,这个答案使我走出去,学习用:g命令钓鱼(也就是说,它使我在Google的这个页面上搜索-vim.wikia.com/wiki/Power_of_g)。
抓取2014年

67

我们可以使用:normal:norm执行给定的普通模式命令。资源。

:%norm jdd

15
这个答案没有引起足够的重视,这可能是因为此处以及链接的凌乱备忘单上都缺少解释。norm命令运行等效于其后字母的普通模式命令。因此,这里运行j向下移动一行,并执行dd删除它。在这种情况下,可以通过添加更多的“ j”将其推广到第X行。
imoatama 2014年

5
而%是1,$的简写(执行从第1行到末尾的以下命令)
Lambart,2014年

3
我对为什么%norm ddj要删除奇数行为什么不起作用感兴趣。
Cyker


8

vim邮件存档

:let i=1 | while i <= line('$') | if (i % 2) | exe i . "delete" | endif | let i += 1 | endwhile

(要在vim命令行上一行输入,将删除行1,3,5,7,...)


4
然后我更喜欢!perl -ne 'print unless $. % 2':-)
亚历克斯·布拉塞特维克

而且,Alex,我绝对希望我的解决方案比您的解决方案更好,但这是一个值得考虑的问题,因为这是这里仅使用vim的唯一明智的解决方案。
Michael Krelin-黑客

宏方法非常容易。
trusktr

1,因为的灵活性,if (expression)这也适用于每一个三线等

5

您始终可以通过shell命令进行管道传输,这意味着您可以使用任何喜欢的脚本语言:

:%!perl -nle 'print if $. % 2'

(或使用“除非”(而不是“ if”),具体取决于所需的行)


您不需要-l切换到Perl ...而且,我想说的awk是,它比Perl普及得多,尽管这些天实际上并没有那么多,并且可以做得更短::%!awk NR\%2,或者:%!awk 1-NR\%2用于其他行。
短暂

4
:%!awk -- '++c\%2'

或者

:%!awk -- 'c++\%2'

取决于您要清除哪一半。


嗯,为什么不使用现有NR变量?
短暂

对。因为我忘记了。;-)但实际上,使用NR的“适当”变体会更长。而且不会有两个漂亮的同行。
Michael Krelin-黑客

:%!awk NR\%2:%!awk 1-NR\%2,如我在另一条评论中所述。这几乎不会更长。
ephemient

1
1-NR比更长c++。是的,我知道这是一个角色。就像我说的那样-真正的原因是我忘记了它。无论如何,看起来人们不喜欢这里的awk之美。
Michael Krelin-黑客

并且NR++c:) 短:
短暂

3

您可以像这样使用Vim自己的搜索和替换功能:将光标放在第一行,然后以普通模式键入:

:.,/fff/s/\n.*\(\n.*\)/\1/g
  • .,/fff/是用于取代的范围内。它的意思是“从此行到与正则表达式匹配的行fff(在本例中为最后一行)。
  • s///是替代命令。它寻找一个正则表达式,并用字符串替换每次出现的正则表达式。的g,只要该正则表达式保持被发现在端装置以重复取代。
  • 正则表达式\n.*\(\n.*\)匹配换行符,然后.*匹配整行(匹配换行符以外的任意数量的字符),再匹配另一个换行符和另一行。括号\(\)记录其中的表达式,因此以后可以使用\1
  • \1 插入分组的换行符并在其后的行之后插入,因为我们也不希望下一行-我们只希望替换机制通过它,因此我们不删除下一个替换项。

这样,您可以控制希望进行删除的范围,而不必使用任何外部工具。


对于文件结尾,无论文件内容如何,​​都可以使用或$代替/fff/
短暂

3

作为另一种方法,如果您的vim支持python,也可以使用python。

:py import vim; cb = vim.current.buffer; b = cb[:]; cb[:] = b[::2]

b = cb[:]暂时将当前缓冲区中的所有行复制到bb[::2]从缓冲区中获取第二行,并将其分配给整个当前缓冲区cb[:]。复制到b由于缓冲区对象似乎不支持扩展切片语法因此必须。

这可能不是“ vim方式”,但是如果您了解python,可能会更容易记住。


2

删除奇数行(1,3,5,..)-> :%s/\(.*\)\n\(.*\)\n/\2\r/g

删除偶数行(2,4,6,..)-> :%s/\(.*\)\n.*\n/\1\r/g

搜索文本(形成第一行),然后是换行符,再搜索更多文本(形成第二行),再是另一个换行符,然后用第一匹配(奇数行)或第二匹配(偶数行)替换上面的内容然后回车。


0

调用sed:

:% !sed -e '2~2 d'

^^^^                  pipe file through a shell command
    ^^^^^^            the command is sed, and -e describes an expression as parameter
            ^^^^^     starting with the second line, delete every second line

-1

你可以在vim中尝试

:1,$-1g/^/+1d

编辑

我会尝试更清楚(两部分)

第一部分选择范围(:from,to
第二部分动作(d删除)

  • 从第一行到最后一行但只有一行的范围(:1,$-1)的范围
  • 全局(g)删除(+1d)下一行

您可以尝试移至文件的第一行并执行,:+1d您将看到下一行消失

我知道它是泥泞的,但它是vim,而且有效


清澈如泥。谢谢!
亨利·亨林森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.