我想在gvim for windows中删除文件中的空白行(不是来自cygwin的vim)。
:g/^$/d # delete all blank lines correctly
:%s/^$//g #can not delete all blank lines
如何表达行尾是一个问题,
我已使用命令%!xxd
详细检查了我的文件
我发现在每一行的末尾有一个 0d0a ,
当行尾由特殊字符$
表示时,
它是否包含 0d0a ?
表达the end of line
命令 g 和 s 的概念是不同的?
:%s/^$\n//g #delete all blank lines correctly
让我感到困惑的是,^$
将包含特殊字符\r\n
,^$
命令中的s
可能不包含特殊字符\r\n
,但是^$
命令中的g
确实包含特殊字符\r\n
。
哪个位置的特殊字符$
指向?在\r\n
之后或\r\n
之前。
答案 0 :(得分:7)
不,这两个命令正在做不同的事情。 :g/^$/d
说“找到空行并删除它们”,而:s/^$//g
表示“在此(当前)行中,将所有无行为替换为无行(仍然在同一行) ”。正如你所注意到的,后者没有意义。
编辑您的编辑:
^$
不包含任何内容。字面意思是“行的开始,然后是行尾”,其中“行”由Vim检测到。 Vim知道\r\n
或\r
或\n
(取决于文件及其创建的操作系统,以及Vim的选项)标记行尾,并相应地对待它。分隔符位于 ^$
之间。
就像你说“我家里的房间” - 这个(至少对我而言)不包括墙壁。当你说^$\n
时,你说的是“空荡荡的房间,还有旁边的木墙”。 s/^$//
“空了(已空)房间”; s/^$\n//
“清空空荡荡的房间并打破墙壁。”
相比之下,对于g
,它再次没有提及\n
。它找到空行(不关心任何分隔符),然后对它执行命令;在您的情况下,命令是d
:删除一行。它会删除整行(以及任何换行符)。例如,如果您编写:g/DELETEME/d
,它将删除任何位于其中的DELETEME的行:它不关心匹配部分中的任何换行,它只删除匹配的行。
答案 1 :(得分:4)
d
表示删除匹配的行。 s
只是一种替代品。本质上,第二个表达式意味着“将^$
与空字符串匹配的行替换”,但这并不会删除它们。你什么也没有替代。 ^
和$
是零宽度断言,无法替换。
答案 2 :(得分:4)
@Amadan和@Explosion Pills都是对的,但我认为你真的需要解释“vim如何思考”你正在编辑的内容。
首先,vim基于vi,这是ex编辑器的前端。尽管vim已经走过了漫长的道路,但它仍然是一个基于行的编辑器。不要在线的末尾寻找魔法角色,因为没有! (当我说vim已经走了很长的路时,我记得添加'whichwrap'
选项的时候。)
我们通常不打算区分,但硬盘上的文件与您在vim中编辑的缓冲区不同(:help buffers
)。该文件是一系列字符(或字节)。当vim读取文件时,它会根据'fileformat'
选项(短格式'ff'
)将它们分成行。由于您在Windows上工作,默认值为'ff'=dos
,这意味着文件中的0d0a
(a.k.a. CRLF或\r\n
)用于分隔行。我有'ff'=unix
,因此当我过滤0a
时,我只看到xxd
。 (在OS X之前,Mac使用0d
,因此有三个标准!)
神奇的EOL角色根本不存在是一件好事,因为这使得vim可以在系统之间移植。作为基于行的编辑器,vim允许您执行各种操作,例如在每行上找到第一个模式匹配并对其执行某些操作。这并不总是你想要的,所以有些人习惯在每个/g
命令的末尾添加:s
,甚至设置'gdefault'
。
回到原来的问题,从缓冲区中删除一行与删除行中的所有字符非常不同。 Ex命令(记住谱系)作用于行,:d
是删除行的命令。 :s
命令将改变一行;不要被常见用法:%s
混淆,它会在缓冲区(:s
)的每一行调用:help :range
。