分类: LINUX
2010-10-18 21:46:53
在使用 vi 编辑器时 — 无论是初次使用的用户,还是有经验的用户 — 大多数人往往只掌握核心命令集,这些命令可以执行最常用的功能:导航或保存文件;插入、更新、删除或搜索数据;退出但不保存修改。
但是,vi 编辑器极其强大,特性和功能非常丰富。即使在多年使用 vi 之后,您仍然可能会发现有不知道的新命令。本文讨论的命令就属于不太为人所知的命令,但是它们可以简化您目前采用的操作方法,让您的工作方式更高效,或者 让您能够完成原来不知道可以用 vi 完成的操作。
vi 编辑器的许多选项可以控制编辑会话的外观和感觉。使用 :set
命令修改 vi 中的会话设置。按 Escape 键进入命令模式之后,可以使用 :set all
命令显示选项和设置的列表。
可以设置的选项之一是 number
,它的作用是打开和关闭行号(见 清单 1)。
# # Internet host table # ::1 localhost 127.0.0.1 localhost loghost 192.168.0.6 centos5 192.168.0.10 appserv 192.168.0.11 webserv 192.168.0.12 test 192.168.0.5 solaris10 # Added by DHCP ~ ~ ~ :set number |
这个命令让 vi 在当前编辑的文件中的每个记录上显示行号。让 vi 进入命令模式之后,可以输入 :set number
并按回车来打开行号(见 清单 2)。
1 # 2 # Internet host table 3 # 4 ::1 localhost 5 127.0.0.1 localhost loghost 6 192.168.0.6 centos5 7 192.168.0.10 appserv 8 192.168.0.11 webserv 9 192.168.0.12 test 10 192.168.0.5 solaris10 # Added by DHCP ~ ~ ~ :set number |
可以使用 :set nonumber
命令关闭行号。还可以使用这个命令和 :set number
命令的简写,即 :set nu
和 :set nonu
。
如果需要快速计算要用 vi 函数处理的行数,显示行号会非常有帮助。当行数很多,可能跨多个屏幕时,行号尤其有用。另外,有时候您知道要处理的行范围,但是需要查明要在 vi 命令中使用的初始和结束行号。
如果希望每次进入 vi 会话时都显示行号,那么在主目录中的 .exrc 文件中添加 set number
行。
在用某些编程语言编写代码时,缩进是样式的重要部分,可以确保代码的可读性更好。如果需要,可以在 vi 编辑器中根据编程语言的样式设置自动缩进。使用 autoindent
打开或关闭自动缩进(见 清单 3)。
#!/bin/ksh # # for file in /etc/* do if [[ -f ${file} ]] ; then echo "${file} is a file" ~ ~ ~ ~ ~ :set autoindent |
在此之后,如果在一行的开头输入空格或制表符,那么后续的新行将会缩进到相同的位置。在命令模式下,输入 :set autoindent
,然后按回车打开自动缩进。通过设置 shiftwidth
确定缩进级别。例如,:set shiftwidth=4
把每级缩进设置为四个空格(见 清单 4)。
#!/bin/ksh # # for file in /etc/* do if [[ -f ${file} ]] ; then echo "${file} is a file" elif [[ -d ${file} ]] ; then echo "${file} is a directory" fi done ~ ~ :set shiftwidth=4 |
在命令模式下,可以使用 >>
命令让现有的一行增加一级缩进,使用 <<
命令减少一级缩进。在这些命令前面加上一个整数,即可让多行增加或减少一级缩进。例如,把游标放在 清单 4 中第 6 行的开头,进入命令模式之后,输入 5>>
就会让下面五行增加一级缩进。清单 5 显示结果。
#!/bin/ksh # # for file in /etc/* do if [[ -f ${file} ]] ; then echo "${file} is a file" elif [[ -d ${file} ]] ; then echo "${file} is a directory" fi done ~ ~ |
可以使用 :set noautoindent
命令关闭自动缩进。还可以使用这个命令和 autoindent
命令的简写,即 :set ai
和 :set noai
。还可以使用 :set ai sw=4
在一个命令中打开缩进并设置缩进级别。
如果希望每次启动 vi 会话时都启用自动缩进并把缩进级别设置为四个空格,那么在主目录中的 .exrc 文件中添加 set ai sw=4
行。
如您所知,在 UNIX® 中执行搜索时,模式匹配是区分大小写的。但是,如果希望 vi 不区分大小写,那么可以使用 :set ignorecase
命令。使用 :set noignorecase
恢复区分大小写。还可以使用简写(:set ic
和 :set noic
)。
如果希望每次进入 vi 会话时都启用不区分大小写的搜索,那么在主目录中的 .exrc 文件中添加 set ignorecase
行。
在 vi 中,可以使用 /
命令搜索字符串,这需要以字面字符串或正则表达式的形式指定要匹配的模式。例如,要想在文件中搜索单词 echo,只需进入命令模式,输入 /echo
,然后按回车。这个命令会找到 清单 6 所示文件的第 3 行的第一个单词。
1 #!/bin/ksh 2 # 3 echo "Starting" 4 file=${1} 5 6 echo ${file} 7 8 if [[ ${file} = 1 ]] ; then 9 ((file=${file}+1)) 10 echo "Adding one gives " \ 11 ${file} 12 fi 13 echo "Ending" 14 exit ~ ~ |
可以使用简单的正则表达式指定寻找包含某一单词而且后面有另一个单词的行。例如,要想寻找包含字符串 echo
、后面有零个或更多字符、之后是字符串 file
的第一行,应该使用 /echo.*file
。在 清单 6 所示的文件中,这个命令会找到第 6 行的第一个单词。
但是,只有这两个字符串出现在同一行上,这个命令才认为是匹配的。如果希望搜索出现在另一个模式或字符串后面的某个模式或字符串,不管这两个模式或字符串是否在同一行上,那么可以指定由分号 (;
) 分隔的两个搜索命令,从而执行复合搜索。例如,要想搜索出现在字符串 {file}+1
后面的字符串 echo
,应该使用 /{file}+1/;/echo/
。在 清单 6 所示的文件中,这个命令会找到第 10 行的第一个单词。
复合搜索对于寻找代码中出现在另一个命令后面的某个命令尤其有用 — 例如,在设置某个变量之后调用函数的地方。
当在文件中搜索要替换的模式时,可以让 vi 把要匹配的任何模式保存在缓冲区中;然后,在执行替换时,可以用缓冲区引用号重放它们。方法是把模式放在 \(
和 \)
之间,这会指示 vi 把模式放在编号的缓冲区(1 到 9)中。在执行替换时,可以用缓冲区引用号 \1
到 \9
引用这些缓冲区。
例如,假设要在 清单 7 所示的文件中搜索以单词 Martin 开头的行并对每个匹配添加前缀 Mr 和后缀 Wicks,那么进入命令模式,输入 vi 命令 :%s/^\(Martin\)/Mr \1 Wicks/g
,然后按回车。
Martin is an IT consultant. Martin likes snowboarding and mountain biking. Martin has worked on UNIX systems for over 15 years. Martin also worked for many years before that on mainframes. Martin lives in London. ~ ~ ~ ~ :%s/^\(Martin\)/Mr \1 Wicks/g |
下面把这个命令分解开解释一下:
:%s
— 指示 vi 执行替换。
/
— 模式分隔符。^\(Martin\)
— 寻找以字符串 Martin
开头的行并把这个字符串保存在缓冲区 1 中。
/
— 模式分隔符。Mr \1 Wicks
— 把找到的字符串替换为字符串 Mr
,加上缓冲区 1 中的内容,再加上字符串 Wicks
。
/
— 模式分隔符。g
— 全局修改(即修改所有匹配的地方)。
在搜索和替换字符串中都可以使用缓冲区引用。
修改的结果见 清单 8。
Mr Martin Wicks is an IT consultant. Martin likes snowboarding and mountain biking. Martin has worked on UNIX systems for over 15 years. Martin also worked for many years before that on mainframes. Mr Martin Wicks lives in London. ~ ~ ~ ~ :%s/^\(Martin\)/Mr \1 Wicks/g