当前位置: 首页 > ds >正文

Linux运维——Vim技巧一

Vim技巧

  • 一、优化重复操作
    • 1.1、 . 命令
    • 1.2、* 命令
    • 1.3、重复修改示例
  • 二、删除单词(daw)
  • 三、对数字做算数运算
  • 四、操作符与动作
  • 五、插入模式
    • 5.1、插入模式下删除
    • 5.2、返回普通模式
    • 5.3、插入-普通模式
    • 5.4、不离开插入模式,粘贴寄存器中的文本
    • 5.4、表达式寄存器
    • 5.5、用字符编码插入字符
  • 六、替换模式
  • 7、可视模式
    • 7.1、选择高亮区域(三种子模式)
    • 7.2、重复执行面向行的可视命令
    • 7.3、面向块的可视模式编辑
    • 7.4、在长短不一的高亮块后添加文本
  • 8、命令行模式
    • 8.1、选定操作范围
    • 8.2、复制和移动(:t和:m)
    • 8.3、在指定范围上执行普通模式命令
    • 8.4、重复上次的Ex命令
    • 8.5、自动补全Ex命令
    • 8.6、把当前单词插入到命令行
    • 8.7、回溯历史命令
    • 8.8、运行Shell命令

一、优化重复操作

1.1、 . 命令

. 命令可以让我们重复上次的修改。“上次修改”可以指很多东西,一次修改的单位可以是字符、整行,甚至是整个文件。

从进入插入模式的那一刻起(例如,输入 i) ,直到返回普通模式时为止 (输入<Esc>) , Vim 会记录每一个按键操作。 做出这样一个修改后再用 . 命令的话,它将会重新执行所有这些按键操作。

# 文档a.txt内容如下Line one
Line two
Line three
Line four# >G 命令会增加从当前行到文档末尾处的缩进层级。
# 如果我们在此命令后使用 . 命令,那么“重复上次修改”会让 Vim 增加从当前行到文档末尾的缩进层级。# 命令如下
>G j. j. j.# 最后文档如下Line oneLine twoLine threeLine four

1.2、* 命令

*命令可以查找当前光标下的单词,等同于/xxxx

Line one
Line two
Line three
Line four

把光标移到单词“Line”上,然后使用 * 命令对它进行查找,这会产生两个结果:

  • 一是光标会跳到下一个匹配项上
  • 二是所有出现这个词的地方都会被高亮显示出来

如果你并没有看到高亮,试着运行一下 :set hls。执行过一次查找“Line”的命令后,现在我们只需按 n 键就可以跳到下一个匹配项。

1.3、重复修改示例

# a.txt内容如下Line one
Line two
Line three
Line four# 将所有Line替换为XXX
# 1. 光标放到第一个Line上,*
# 2. cw  删除Line,输入 XXX,<ESC>
# 3. 按n跳转到下一个匹配的Line,按.重复修改
# 即 * cw XXX <ESC> n. n. n.

二、删除单词(daw)

# 光标位于行尾处的字符“h”上,而我们想要删除单词“nigh”
The end is nigh

反向删除:
db 命令删除从光标起始位置到单词开头的内容,但会原封未动地留下最后一个字符 “h” ,再按一下 x 键就可以删除这个捣乱的字符。

正向删除:
先用 b 命令把光标移到单词的开头,移动好后,就可以用一个 dw 命令删掉整个单词。

删除整个单词:
可以使用更为精准的 aw 文本对象 (text object) , 而不是用动作命令。

使用daw一次删除整个单词,可以把 daw 命令解读为“delete a word” ,这样比较容易记忆。

三、对数字做算数运算

<C-a><C-x> 命令分别对数字执行加和减操作。在不带次数执行时,它们会逐个加减,但如果带一个次数前缀,那么就可以用它们加减任意整数。

如果光标不在数字上 <C-a> 命令会“把当前光标之上或之后的数值加上 [count]”。因此,如果光标不在数字上,那么 <C-a> 命令将在当前行正向查找一个数字,如果找到了,它就径直跳到那里。我
们可以利用这一点简化操作。

# 假设光标位于首字符
This is 2 times;
This is 3 times;# 按下 10<C-a>  后
This is 12 times;
This is 3 times;

四、操作符与动作

操作符 + 动作命令 = 操作

d{motion} 命令可以对一个字符(dl)、一个完整单词(daw)或一整个段落(dap)进行操作,它作用的范围由动作命令决定。c{motion}y{motion}以及其他一些命令也类似,它们被统称为操作符(operator)。你可以用:h operator 来查阅完整的列表,下表总结了一些比较常见的操作符。

操作符动作
c修改
d删除
y复制到寄存器
g~反转大小写
gu转换为小写
gU转换为大写
>增加缩进
<减小缩进
=自动缩进
!使用外部程序过滤{motion}所跨越的行

操作符与动作命令的结合形成了一种语法。这种语法的第一条规则很简单,即一个操作由一个操作符,后面跟一个动作命令组成。假如我们已经知道如何用 daw 删除一个单词,然后又学到 gU 命令。它也是个操作符,所以我们可以用 gUaw 把当前单词转换成大写形式。如果我们的词汇进一步扩充,学会了作用于段落的 ap 动作命令,就会发现我们可以进行两个新的操作:用 dap 删除整个段落,或者用 gUap 把整段文字转换为大写。

Vim 的语法只有一条额外规则,即当一个操作符命令被连续调用两次时,它会作用于当前行。所以 dd 删除当前行,而 >> 缩进当前行。gU 命令是一种特殊情况,我们既可以用 gUgU ,也可以用简化版的 gUU 来使它作用于当前行。

五、插入模式

5.1、插入模式下删除

在插入模式下,除了退格键可以删除。另外,我们还可以用下面这些组合键:

按键操作用途
<C-h>删除前一个字符(同退格键)
<C-w>删除前一个单词
<C-u>删至行首

5.2、返回普通模式

在插入模式下,除了<Esc>键可以返回普通模式。另外,我们还可以用下面这些组合键:

按键操作用途
<Esc>切换到普通模式
<C-[>切换到普通模式
<C-o>切换到插入-普通模式

5.3、插入-普通模式

插入-普通模式是普通模式的一个特例,它能让我们执行一次普遍模式命令。在此模式中,我们可以执行一个普通模式命令,执行完后,马上就又返回到插入模式。要从插入模式切换到插入-普通模式,可以按 <C-o>

在当前行正好处于窗口顶部或底部时,有时我会滚动一下屏幕,以便看到更多的上下文。用 zz 命令可以重绘屏幕,并把当前行显示在窗口正中,这样就能够阅读当前行之上及之下的半屏内容。我常常会键入 <C-o>zz,在插入-普通模式中触发这条命令。此操作完成后就会直接回到插入模式,因此我可以不受中断地继续打字。

5.4、不离开插入模式,粘贴寄存器中的文本

我们想把本书的书名插到最后一行,以补全该行。由于书名在第一行的开头已经出现过了,我们将把它复制到一个寄存器中,然后在插入模式中把它添加到第二行结尾。

按键操作缓冲区内容
yt,Practical Vim, by Drew Neil
Read Drew Neil’s
jA空格Practical Vim, by Drew Neil
Read Drew Neil’s
<C-r>0Practical Vim, by Drew Neil
Read Drew Neil’s Practical Vim``
.<Esc>Practical Vim, by Drew Neil
Read Drew Neil’s Practical Vim.

yt, 命令把“Practical Vim”复制到复制专用寄存器中,然后我们在插入模式中,按 <C-r>0把刚才复制的文本粘贴到光
标所在位置。

对面向字符的寄存器使用 <C-r>{register} 命令,其中{register}是我们想要插入的寄存器的名字。

5.4、表达式寄存器

大部分的 Vim 寄存器中保存的都是文本,要么是一个字符串,要么是若干行的文本。删除及复制命令允许我们把文本保存到寄存器中,而粘贴命令则允许我们把寄存器中的内容插入到文档里。

不过表达式寄存器则是个另类,它可以用来执行一段 Vim 脚本,并返回其结果。可以用 = 符号指明使用表达式寄存器。在插入模式中,输入 <C-r>= 就可以访问这一寄存器。这条命令会在屏幕的下方显示一个提示符,我们可以在其后输入
要执行的表达式。输入表达式后敲一下 <CR>, Vim 就会把执行的结果插入到文档的当前位置了。

假设我们刚输入完下列内容:

6 chairs, each costing $35, totals $

我们想算一下总价,不过没必要找个信封在背面做演算,Vim 可以帮我们做这件事,我们甚至连插入模式都不用退出。

按键操作缓冲区内容
A6 chairs, each costing $35, totals $
<C-r>=6*35<CR>6 chairs, each costing $35, totals $210

5.5、用字符编码插入字符

Vim 可以用字符编码(Character Code)插入任意字符。使用此功能可以很方便地输入键盘上找不到的符号。

只要知道某个字符的编码,就可以让 Vim 插入该字符,我们可以用这种方式插入任意字符。要根据字符编码插入字符,只需在插入模式中输入 <C-v>{code}即可,其中{code}是要插入字符的编码。

Vim 所接受的字符编码共包含 3 位数字。例如,假设我们想插入大写字母“A”,它的字符编码是 65,因此我们需要输入 <C-v>065

然而,如果我们想插入一个编码超过 3 位数的字符该怎么办?比方说,Unicode基本多文种平面 (Unicode Basic Multilingual Plane) 的地址空间最大会有 65535 个字符。解决方法是可以用 4 位十六进制编码来输入这些字符,即输入<C-v>u{1234} (注意数字前的 u ) 。假设我们想插入字符编码为 00bf 的反转问号( “¿” ) ,只需在插入模式中输入 <C-v>u00bf 即可。

如果你想知道文档中任意字符的编码,只需把光标移到它上面并按 ga 命令,然后屏幕下方就会显示出一条消息,分别以十进制和十六进制的形式显示出其字符编码。

另外,如果 <C-v> 命令后面跟一个非数字键,它会插入这个按键本身所代表的字符。例如,如果启用了‘expandtab’ 选项,那么按 <Tab> 键将会插入空格而不是制表符。然而,按 <C-v><Tab> 则会一直插入制表符,不管‘expandtab’ 选项激活与否。

按键操作用途
ga查看编码
<C-v>{123}以十进制字符编码插入字符
<C-v>u{1234}以十六进制字符编码插入字符
<C-v>{nondigit}按原义插入非数字字符
<C-k>{char1}{char2}插入以二合字母{char1}{char2}表示的字符

六、替换模式

在替换模式中输入会替换文档中的已有文本,除此之外,该模式与插入模式完全相同。

命令用途
R普通模式进入替换模式
r{char}/gr{char}单次版本的替换模式及虚拟替换模式,允许我们覆盖一个字符,之后马上又回到普通模式

假设有如下一段文本:

Typing in Insert mode extends the line. But in Replace mode
the line length doesn't change.

我们想把这两个单独的句子合并成一句话,为此,需要把句号改成逗号,并将单词“But”中的“B”改为小写。

按键操作缓冲区内容
{start}Typing in Insert mode extends the line. But in Replace mode the line length doesn’t change.
f.Typing in Insert mode extends the line. But in Replace mode the line length doesn’t change.
R,空格b<Esc>Typing in Insert mode extends the line. but in Replace mode the line length doesn’t change.

7、可视模式

可视模式允许我们选中一个文本区域并在其上操作。我们仍可以把 h、j、k及 l当成光标键使用;也可以用 f{char} 跳到当前行的某个字符上,然后用 ; 和 , 命令相应地正向或反向重复此跳转;甚至还可以用查找命令(以及 n / N 命令)跳转到匹配指定模式的地方。每次在可视模式中移动光标,都会改变高亮选区的边界。

7.1、选择高亮区域(三种子模式)

激活可视模式:

命令用途
v激活面向字符的可视模式
V激活面向行的可视模式
<C-v>激活面向列块的可视模式
gv重选上次的高亮选区

可视模式间切换:

按键操作用途
<Esc> / <C-[>回到普通模式
v/V/C-v切换到普通模式(在对应的面向字符可视模式、面向行的可视模式或面向列块的可视模式中使用时)
v切换到面向字符的可视模式
V切换到面向行的可视模式
<C-v>切换到面向列块的可视模式
o切换高亮区的活动端

切换选区的活动端:

高亮选区的范围由其两个端点界定。其中一端固定,而另一端可以随光标自由移动,我们可以用 o 键来切换其活动的端点。在定义选区时,如果定义到一半时,才发现选区开始的位置不对,此时用这个键会很方便,我们用不着退出可视模式再
从头开始,只需按一下 o,然后重新调整选区的边界即可。下面的操作对此功能进行了演示:

按键操作缓冲区内容
{start}Select from here to here.
vbbSelect from here to here.
oSelect from here to here.
eSelect from here to here.

7.2、重复执行面向行的可视命令

假设有一段 Python 代码的缩进有些问题,如下所示:

def fib(n):a, b = 0, 1while a < n:
print a,
a, b = b, a+b
fib(42)

这段代码的每级缩进使用 4 个空格,首先我们得对 Vim 进行配置,使之符合此缩要想让 < 和 > 命令正常工作,我们需要把 ‘shiftwidth’ 及 ‘softtabstop’进风格。

:set shiftwidth=4 softtabstop=4 expandtab
# {start}   def fib(n):a, b = 0, 1while a < n:
print a, # 光标位于p
a, b = b, a+b
fib(42)# Vj 
def fib(n):a, b = 0, 1while a < n:
print a,    # 选中此行
a, b = b, a+b  # 选中此行
fib(42)# >.  重复缩进
def fib(n):a, b = 0, 1while a < n:print a,a, b = b, a+b
fib(42)

7.3、面向块的可视模式编辑

假设有如下一个纯文本表格:

Chapter			Page
Normal mode		15
Insert mode		31
Visual mode		44

我们想用管道符画一条竖线来隔开这两列文本,使之看起来更像一个表格。但是在此之前,要先减少两列之间的间隔,使它们不要分得这么开。用面向列块的可视模式可以完成这两处修改,

{start} # 光标放在Chapter和Page中间
<C-v>3j  # 向下选3行
x...     # 删除并重复3次
gv       # 再次选区高亮区域
r|		 # 替换模式下替换为| 
yyp		 # 光标在Chapter行,复制并粘贴该行
Vr-		 # 切换到行可视模式,替换为-# 结果为
Chapter			|	Page
--------------------
Normal mode		|	15
Insert mode		|	31
Visual mode		|	44

7.4、在长短不一的高亮块后添加文本

var foo = 1
var bar = 'a'
var foobar = foo + bar

这段代码有连续 3 行,每行的长度各不相同,而我们想在每行结尾添加一个分号。

{start}  # 开始,光标在首行1位置上
<C-v>jj$  #开启块可视模式,选中到行尾
A;		# 尾部添加;
<Esc> # 退出

确定好选区后,用 A 命令就可以在每行的结尾添加内容。此命令让我们进入插入模式,且使光标停留在顶行。处于插入模式期间,任何输入的内容只出现在顶行,然而一旦返回到普通模式,这些修改就会被扩散到其余选中的行上。

8、命令行模式

命令行模式会提示我们输入一条 Ex 命令、一个查找模式,或一个表达式。在按下 : 键时,Vim 会切换到命令行模式。这个模式和 shell 下的命令行有些类似, 我们可以输入一条命令, 然后按 <CR> 执行它。 在任意时刻, 我们都可以按 <Esc>键从命令行模式切换回普通模式。

操作缓冲区文本的Ex命令:

命令用途
:[range]delete [x]删除指定范围内的行[到寄存器 x中]
:[range]yank [x]复制指定范围的行[到寄存器 x中]
:[line]put [x]在指定行后粘贴寄存器 x中的内容
:[range]copy {address}把指定范围内的行拷贝到{address} 所指定的行之下
:[range]move {address}把指定范围内的行移动到 {address} 所指定的行之下
:[range]join连接指定范围内的行
:[range]normal {commands}对指定范围内的每一行执行普通模式命令 {commands}
:[range]substitute/{pattern}/{string}/[flags]把指定范围内出现{pattern}的地方替换为{string}
:[range]global/{pattern}/[cmd]对指定范围内匹配{{pattern}的所有行,在其上执行Ex 命令{cmd}

8.1、选定操作范围

很多 Ex 命令可以用 [range] 指定要操作的范围。我们可以用行号、位置标记或是查找模式来指定范围的开始位置及结束位置。

<!DOCTYPE html>
<html>
<head><title>Practical Vim</title></head>
<body><h1>Practical Vim</h1></body>
</html>

我们将使用:print命令作为演示。 这条命令只是简单地在 Vim 命令行下方回显指定行的内容,它不产生什么实际影响,不过可以用它来说明一个范围由哪些行构成。当然,你可以试着把以下示例中的:print 换成诸如:delete:join:substitute:normal这样的命令,这样就能真切地感受到 Ex 命令是多么有用。

用行号作为地址:

# 如果输入一条只包含数字的 Ex 命令,那么 Vim 会把这个数字解析成一个地址,并把光标移动到该数字所指定的行上。
:1
:p
# 或
:1p#输出
1 <!DOCTYPE html>

用地址指定一个范围:

# 语法   :{start},{end}
# 打印2到5行
:2,5p# 输出2 <html>3 <head><title>Practical Vim</title></head>4 <body><h1>Practical Vim</h1></body>5 </html># 当前行到最后一行
.,$p# 全文
%p  
# 等价于  1,$p

用高亮选区指定范围:

我们也可以用高亮选区选定一个范围,而不是用数字指定。如果我们先执行 2G,再跟着执行 VG,就会选中如下一个高亮选区:

在这里插入图片描述

如果现在按下 : 键,命令行上就会预先填充一个范围 :'<,'>。这个范围看起来有点晦涩难懂,不过你可以简单地把它理解为一个代表高亮选区的范围。接下来我们就可以输入一条 Ex 命令,使它在每个被选中的行上执行:

:'<,'>p

用模式指定范围:

Vim 也接受以模式作为一条 Ex 命令的地址,如下所示:

:/<html>/,/<\/html>/p# 输出2 <html>3 <head><title>Practical Vim</title></head>4 <body><h1>Practical Vim</h1></body>5 </html>

这个范围看起来比较复杂,但实际上它符合范围的一般形式:{start},{end}。在本例中, {start} 地址是模式 /<html>/,而 {end} 地址是 /<\/html>/。换句话说,这个范围由 <html> 开标签所在的行开始,到对应闭标签所在的行结束。

用偏移对地址进行修正:

假设我们想对位于<html></html>之间的每一行都运行一条 Ex 命令,但是不想包括 <html></html> 标签所在的行,那么可以为之加上偏移:

# 语法 :{address}+n
:/<html>/+1,/<\/html>/-1p#输出3 <head><title>Practical Vim</title></head>4 <body><h1>Practical Vim</h1></body>

总结:

符号地址
1文件的第一行
$文件的最后一行
0虚拟行,位于文件第一行上方
.光标所在行
'm包含位置标记 m的行
'<高亮选区的起始行
'>高亮选区的结束行
%整个文件(:1,$ 的简写形式)

8.2、复制和移动(:t和:m)

  • :copy 命令(及其简写形式 :t)让我们可以把一行或多行从文档的一部分复制到另一部分
  • :move 命令(及其简写形式 :m)则可以让我们把一行或多行移到文档的其他地方
Shopping listHardware StoreBuy new hammerBeauty ParlorBuy nail polish removerBuy nails

:t命令复制行:

# 语法
:[range]copy {address}

这个购物清单还没完成,我们也要在五金商店(hardware store)买些钉子(nails) 。为完成这个清单,我们将重用文件的最后一行,即在“Hardware Store”下面为之创建一份副本。

{start}  #开始,光标位于第二行H位置
:6t.     # 复制第6行,并粘贴到当前行下# 结果如下1 Shopping list2     Hardware Store3         Buy nails4         Buy new hammer5     Beauty Parlor6         Buy nail polish remover7         Buy nails

应用实例:

命令用途
:6t.把第 6行复制到当前行下方
:t6把当前行复制到第 6行下方
:t.为当前行创建一个副本(类似于普通模式下的 yyp)
:t$把当前行复制到文本结尾
:'<,'>t0把高亮选中的行复制到文件开头

:m命令移动行:

# 语法
:[range]move {address}

假设我们想把 Hardware Store 一节移到 Beauty Parlor 一节的下方,用 :move 就可以实现这一点:

{start}		# 开始,光标位于第2行H位置
Vjj			# 进入列视图模式,并向下选中2行
:'<,'>m$	# 将选中高亮区域移动到最后一行后面# 结果1 Shopping list2     Beauty Parlor3         Buy nail polish remover4         Buy nails5     Hardware Store6         Buy nails7         Buy new hammer

8.3、在指定范围上执行普通模式命令

如果想在一系列连续行上执行一条普通模式命令,我们可以用 :normal 命令。此命令在与. 命令或宏结合使用时,我们只需花费很少的努力就能完成大量重复性任务。

们将在下面文件的每行后都添加一个分号,以此作为演示。

var foo = 1
var bar = 'a'
var baz = 'z'
var foobar = foo + bar
var foobarbaz = foo + bar + baz
{start} 		# 光标位于第一行v位置
A;<Esc>			# 移动行尾进入插入模式输入;然后返回普通模式
jVG				# 移动到下一行,进入行视图模式,选中到文档尾部
:'<,'>normal .	#进入命令模式,normal命令执行.# 结果1 var foo = 1;2 var bar = 'a';3 var baz = 'z';4 var foobar = foo + bar;5 var foobarbaz = foo + bar + baz;

命令模式中,可以使用如下命令完成相同操作:

:%normal A;

8.4、重复上次的Ex命令

. 命令可以重复上次的普通模式命令。然而,如果想重复上次的 Ex 命令的话,我们得使用 @: 才行。

例如,下面两条命令在遍历缓冲区列表的条目时非常有用,用 :bn[ext] 可以在列表中逐项正向移动,而 :bp[revious] 命令则进行反向移动 。 假设缓冲区列表中有大约十几个条目, 而我们打算逐个查看每个缓冲区,因此可以输入一次下面的命令:

:bnext

然后再用 重复执行此命令。

8.5、自动补全Ex命令

如同在 shell 中一样,在命令行上也可以用 <Tab> 键自动补全命令。

Vim 在选取 Tab 补全的补全项时非常智能,它会检查命令行上已经输入的上下文,然后再构建合适的补全列表。例如,可以这样输入:

:col<C-d>
colder 	colorscheme

<C-d> 命令会让 Vim 显示可用的补全列表。另外,如果
我们多次按 <Tab> 键的话,命令行上会依次显示 colder、colorscheme,然后再回到最初的 col,如此循环往复。要想反向遍历补全列表,可以按 <S-Tab>

8.6、把当前单词插入到命令行

即使是在命令行模式下, Vim 也始终知道光标位于何处以及哪个分割窗口处于活动状态。为节省时间,我们可以把活动窗口中的当前单词(或字串)插入到命令行中。

在 Vim 的命令行下, <C-r><C-w> 映射项会复制光标下的单词并把它插入到命令行中。我们可以利用这一功能减少击键的次数。

假设我们想把下面这段代码中的变量 tally重命名为 counter:

var tally;
for (tally=1; tally <= 10; tally++) {// do something with tally
};

把光标移到单词 tally上后,用 * 命令就可以查找它出现的每处地方(* 命令等效于输入/\<<C-r><C-w>\><CR> 序列。

{start} 		# 开始光标位于第一行t位置
*				# 查找出所有tally
cwcounter<Esc>	#cw命令删除tally并进入插入模式tally,然后返回普通模式
:%s//<C-r><C-w>/g  # 然 后 , 我 们 将 用 :substitute 命 令 完 成 其 余 的 修 改 。 由 于 光 标 已 经 在 单 词“counter”上了,因此我们无需再次输入它,而是直接用 <C-r><C-w>映射项把它插入到替换域

8.7、回溯历史命令

Vim 会记录命令行模式中执行过的命令,并提供了两种方式回溯这些命令,用光标键回滚之前的命令或调出命令行窗口查看先前的命令。

先按 : 键切换到命令行模式,在保持提示符为空的情况下按 <Up> 键,此时最后执行的那条 Ex 命令就会被填充到命令行上。再接着按 <Up> 键的话,就可以回到更早的 Ex 历史命令;按 <Down> 键的话,则会沿相反方向滚动。

Vim 缺省会记录最后 20 条命令,对内存越发便宜的现代计算机来说,保存更多历史命令只是小菜一碟,因此我们可以修改 ‘history’ 选项,以提高其保存的上限。

你可以试着把下面这行内容加入 vimrc 文件:

set history=200

8.8、运行Shell命令

不用离开 Vim 就能方便地调用外部程序。更棒的是,我们还可以把缓冲区的内容作为标准输入发送给一个外部命令, 或是把外部命令的标准输出导入到缓冲区里。

在 Vim 的命令行模式中,给命令加一个叹号前缀就可以调用外部程序。例如,如果想查看当前目录的内容,可以运行下面的命令:

:!ls

在 Vim 的命令行中,符号 % 代表当前文件名 。在运行那些操作当前文件的外部命令时,我们可以使用它。例如,如果我们正在编辑某个 脚本 文件,那么可以用下面的方式执行此文件:

:!sh %

:!{cmd} 这种语法适用于执行一次性命令,但是如果想在 shell 中执行几条命令要怎么做?对这种情况,可以执行 Vim 的 :shell 命令来启动一个交互的 shell 会话。用 exit 命令可以退出此 shell 并返回 Vim。

把缓冲区内容作为标准输入或输出:

在用 :!{cmd}时,Vim 会回显 {cmd} 命令的输出。如果命令的输出很少或没有输出,这工作得很好;但如果命令会产生大量输出,这样回显用处不大。另外一种做法是我们可以用 :read !{cmd} 命令,把 {cmd} 命令的输出读入当前缓冲区中。

:read !{cmd} 命令让我们把命令的标准输出重定向到缓冲区。正如你所期望的一样, :write !{cmd} 做相反的事。它把缓冲区内容作为指定 {cmd} 的标准输入。

使用外部命令过滤缓冲区内容:

当给定一个范围时,:!{cmd} 命令就具有了不同的含义。由[range]所指定的行会传给{cmd} 作为标准输入,然后又会用 {cmd} 的输出覆盖 [range]内原本的内容。

换一种说法就是 [range] 内的文本会被指定的 {cmd} 进行过滤。Vim 把过滤器定义为 “一个由标准输入读取文本, 并对其进行某种形式的修改后输出到标准输出的程序” 。

作为演示,我们将用外部的 sort 命令对下列 CSV 文件中的记录进行排序:

first name,last name,email
john,smith,john@example.com
drew,neil,drew@vimcasts.org
jane,doe,jane@example.com

我们想基于第二个字段“姓氏”来重排这些记录。我们可以用 -t’,’ 参数告诉sort 命令,这些记录以逗号分隔,然后再用 -k2 参数指定按第二个字段进行排序。
因为文件的第一行是标题信息,我们想把它们保留在文件顶部,因此需要用范围 :2,$ 把它排除在排序范围之外。下列命令将完成我们想要的功能:

:2,$!sort -t',' -k2#结果:1 first name,last name,email2 jane,doe,jane@example.com3 drew,neil,drew@vimcasts.org4 john,smith,john@example.com

总结:

命令用途
:shell启动一个 shell (输入 exit返回 Vim)
:!{cmd}在 shell 中执行 {cmd}
:read !{cmd}在 shell 中执行 {cmd} ,并把其标准输出插入到光标下方
:[range]write !{cmd}在 shell 中执行 {cmd} ,以 [range] 作为其标准输入
:[range]!{filter}使用外部程序 {filter} 过滤指定的 [range]
http://www.xdnf.cn/news/3756.html

相关文章:

  • LeetCode —— 102. 二叉树的层序遍历
  • 设计模式简述(十七)备忘录模式
  • yolov5 train笔记4 roboflow
  • Android Compose 中 Side Effects 和 State 相关的 API 使用
  • 数据仓库方法论书籍及其阅读建议
  • Linux 库文件详解
  • 自动化测试项目1 --- 唠嗑星球 [软件测试实战 Java 篇]
  • 旧版本NotionNext图片失效最小改动解决思路
  • 解决跨域问题
  • 【质量管理】现代TRIZ问题识别中的功能分析——相互接触分析
  • HarmonyOS NEXT第一课——HarmonyOS介绍
  • FastAPI中的复杂查询与原子更新指南
  • 柔性超声耦合剂的选择与设计-可穿戴式柔性超声耦合剂面临的难题
  • C# 多态性详解:从静态到动态的编程艺术
  • PMP-第七章 项目成本管理(一)
  • 2.1 行列式
  • 【C++】平衡二叉树(AVL树)迭代版
  • 高中数学联赛模拟试题精选学数学系列第7套几何题
  • 【单片机数码管实现第一位开始走0~9,1s后第二位再开始亮】2022-5-2
  • K8S - StatefulSet 与 DaemonSet - 有状态应用部署与节点管理策略
  • QGraphicsView QGraphicsScene QGraphicsItem 的关系
  • 计算几何(简单旋转卡壳)2024昆明邀请赛
  • [FPGA Video IP] Multi-Scaler
  • [Control-Chaos] Heart Broken(心臟破裂)
  • 完整的 VS Code + CMake + Qt + GCC 项目构建方案:EXE 程序与多个 DLL 库
  • Linux运维中常用的磁盘监控方式
  • # 前后端分离象棋对战项目开发记录
  • 安卓游戏APK文件解密与编辑的完整攻略
  • NVIDIA Performance Primitives (NPP) 库全面解析
  • string--OJ1