- 论坛徽章:
- 0
|
作为一个而立之年的单身男屌丝,现在也不得不为了女人的事耽误一点学习时间,因此学习进度稍有耽搁。
最近在学习正则表达式相关内容. 正则表达式的强大,加上VIM和egrep等工具配合,实现一些查找替换等工作,简直是手到擒来。
看了《精通正则表达式》的前三章,书中内容主要是用Perl来讲解正则表达式的使用,而我学习正则表达式的目的就是配合vim和egrep来提高日常工作的效率。书中也提到正则表达式分很多流派,也就是说正则表达式在各种语言和工具中表达方式不尽相同,因此我打算在了解正则表达的一些基础知识后便停止进一步的学习,把工作重点转移到linux编程上来。
下面我来总结一下正则表达式在VIM中的使用。
1. 搜索命令 (:help pattern-searches)
/{pattern}[/]<CR> 搜索光标后面的第[count]个{pattern}
/{pattern}/{offset}<CR> 搜索光标后面的第[count]个{pattern},并跳到{pattern}所在位置的offset处。
其中{offset}取值:
[num] 向下num行
+[num] 向下num行
-[num] 向上num行
e[+num] 匹配结果的结尾的右边第num个字符
e[-num] 匹配结果的结尾的左边第num个字符
s[+num] / b[+num] 匹配结果的开头的右边的第num个字符
s[-num] / b[-num] 匹配结果的开头的左边的第num个字符
;/{pattern} 执行另一个搜索,例如/the/;/word<CR>:先找到一个the,然后再搜索word。
/<CR> 正向查找最后一次使用的{pattern}的第[count]个匹配(并使用上次的offset)
//{offset}<CR> 执行最后一次查找,但使用新的offset值
以上几个命令的/替换为?即可实现反向查找功能。
其他命令:
n 执行最后一次查找
N 反向执行最后一次查找
* 正向查找光标下的单词
# 反向查找光标下的单词
g* 正向查找光标下的单词,非整个单词匹配,也匹配单词的一部分。
g# 反向查找光标下的单词,非整个单词匹配,也匹配单词的一部分。
gd 跳到局部变量的声明处 (定位并不十分准确)
gD 跳到全局变量的声明处 (定位并不十分准确)
执行查找命令后,如果使用了hlsearch选项,则搜索结果会被高亮,如果想清除搜索结果,则输入:let @/=""
在指定范围内搜索,如,在50-100行之间搜索word,则输入/%>50l%<100lword
2. 正则表达式(VIM中称之为模式)
搜索有几种模式:magic(\m), nomagic(\M), very magic(\v), very nomaigc(\V)
very magic模式下,除了0-9,A-Z,a-z,_以外的所有字符都具有特殊意义。这样pattern将显得非常清晰,可读性好,与Perl,Python的正则表达式更为接近。在搜索的起始位置加入\v开关开启very magic模式。以下内容仅适用于very magic模式。
very nomgic模式下,除了\外,都不具有特殊意义。所以在原意匹配的时候,用\V开关最方便!
VIM下元字符的修饰符
* 0或者更多
+ 1或者更多
= 0或者1
? 0或者1, 与=相同,但不能用于?的向后查找
{n,m} n到m
{n} n
{n,} 至少n
{,m} 0到m
{} 0或者更多, 与*相同
{-n,m} n到m,尽可能少的匹配.
{-n} 匹配n次。
{-n,} 匹配至少n次,尽可能少的匹配.
{-,m} 0到m,尽可能少的匹配.
{-} 0或者更多,尽可能少的匹配.
------------------------------------------------------------------------
VIM下的元字符
^ 行首(zero-width)
\_^ 行首(zero-width)
$ 行尾(zero-width)
\_$ 行尾(zero-width)
. 除了换行符的其他任意字符
\_. 任意一个字符,包括换行符
< 一个单词的开始(zero-width)
> 一个单词的结束(zero-width)
\zs 设置匹配的开始
\se 设置匹配的结束
%^ 文件的开始(zero-width)
%$ 文件的结束(zero-width)
%V 在选择的区域内进行匹配(可视模式下)(zero-width)
%# 匹配光标所在的位置 (zero-width)
%'m 匹配标记m所在位置(zero-width)
%<'m 匹配标记m之前的内容(不适用于very magic模式,其他模式下\%<'m)
%>'m 匹配标记m之后的内容(不适用于very magic模式,其他模式下\%>'m)
(关于标记, 使用m{letter}命令在当前光标位置创建一个标记,然后可以使用`{letter}命令回到这个位置,其中letter是小写字母代表局部标记,大写字母代表全局标记)
%23l 在第23行内进行匹配。(zero-width)
%>23l 在第23行以后进行匹配。(zero-width)
%<23l 在第23行以前进行匹配。(zero-width)
%23c 在第23列进行匹配。
%>23c 在第23列之后进行匹配。
%<23c 在第23列之前进行匹配。
%23v Matches in a specific virtual column.
%<23v Matches before a specific virtual column.
%>23v Matches after a specific virtual column.
字符类:
\i 标识符字符, (isident)
\I 与\i类似, 但不包括数字
\k keyword 字符(iskeyword)
\K 与\k类似, 但不包含数字
\f 文件名字符,(isfname)
\F 与\f类似,但不包括数字
\p 可打印字符,(isprint)
\P 与\p类似,但是不包含数字
\s 空白字符(<Space> and <Tab>
\S 非空白字符,与\s相对
\d 数字[0-9]
\D 非数字[^0-9]
\x 十六进制数字[0-9A-Fa-f]
\X 非十六进制数字[^0-9A-Fa-f]
\o 八进制数字 [0-7]
\O 非八进制数字[^0-7]
\w word字符 [0-9A-Za-z_]
\W 非word字符[^0-9A-Za-z_]
\h head of word字符 [A-Za-z_]
\H 非head of word字符 [^A-Za-z_]
\a 英文字母 [A-Za-z]
\A 非英文字母[^A-Za-z]
\l 小写字母 [a-z]
\L 非小写字母 [^a-z]
\u 大写字母[A-Z]
\U 非大写字母[^A-Z]
\_x 其中x可为以上任一字符,表示包括换行符的集合
\e <ESC>
\t <Tab>
\r <CR>
\b <BS>
\n 换行符
~ 上一个substitute使用的替换字符串
() 把括号内的内容封装为一个atom, 并把匹配的值保存在参数变量中\1到\9中,参数的顺序按照左括号出现的顺序。
%() 作用同(),但是不把括号内的模式保存为参数,这样可以提高匹配的效率。
\1 - \9 表示用圆括号匹配的参数变量
[] 匹配方括号中的任意一个字符
%[] 一系列可选的匹配字符串
例如:/\vfu%[nction] 可以匹配:fu, func, function.
%d 匹配指定的十进制表示的字符,例如%d48 == '0'
%x 匹配指定的十六进制表示的字符
%o 匹配指定的八进制表示的字符
%u 匹配指定的多字节字符 %u1234
%U 匹配指定的长多字节字符 %U12345678
#以下几个特殊字符实在用语言表达不太清楚...
@= 用0宽度匹配之前的元字符(Perl: (?=pattern)).
@! 如果右边不能匹配@!之前的元字符,则匹配0个宽度,(Perl?!pattern)).
如: /\vfoo(bar)@! 匹配后面不是bar的foo
@<= 类似Perl中的(?<=pattern)
@<! 类似Perl中的(?<!pattern)
@> 类似Perl中的(?>pattern)
----------------------应用---------------------------
例如有文本:abcdefb
.{-1,}b 匹配:ab和cdefb
.{1,}b 匹配:abcdefb
在指定范围内进行匹配(可指定行与列的范围):
例如在第23行到第50行之间查找word,则/\v%>22l%<51lword
查找两个连续的单词,使用参数变量功能
/\v<(\w+)\s*\1>
匹配位置(不匹配任何字符,只匹配一个位置):
(1) 匹配行首 /\v^/
然后执行 :10,20 s//#/g 即可在第10-20行的行首添加‘#’
(2) 我在工作中经常遇到这样的问题,需要在11223344556677889900AABBCCDDEEFF这样的一串十六进制数中,按两个一组在前面插入\x以组成C语言中的字符串。可以先这样做,匹配每组(两个字节)之间的位置,然后替换为\x。
写出查找模式:/\v\ze(\x\x)+>/
进行替换::%s//\\x/g
替换后的结果:\x11\x22\x33\x44\x55\x66\x77\x88\x99\x00\xAA\xBB\xCC\xDD\xEE\xFF
(3) 匹配特定上下文的字符串:
例如有两行文本如下:
1. this text have two line.
2. one two three
如果想只想匹配第二行中的two,则可使用/\vone\s*\zstwo\zethree/ (首先要匹配整个表达式,然后实际匹配的内容为\zs开始到\ze结束的部分,如果只指定\zs,则匹配\zs到结束的部分,只指定\ze与之类似)
或者使用/\v(one\s*)@<=two(\s*three)@=/ (匹配的two的条件是:two的左边要有个one\s*,右边有个\s*three)
|
|