前面我们了解了部分linux shell的相关特性,下面的链接是第4篇文章:linux_shell_4_shell特性
这里我们来继续讨论linux shell中至关重要的一个特性: 正则表达式 (regular expression)。
正则表达式主要是用来处理字符流的,它的处理单位是行字符文本,也就是说正则表达式的处理对象是: 字符行。
【1】单字符通配
在bash中,我么可以使用 ? 来匹配单个字符,但是在正则表达式中,? 不能用作单个字符的通配。这一点需要引起注意。
在正则表达式中利用:
[a-z] #匹配lowcase char [A-Z] #匹配upcase char
[a-zA-Z] #匹配任意char 字符
这三个表达式仅表示通配一个字符。
这里我们以鸟哥的一个在线文档为例: http://linux.vbird.org/linux_basic/0330regularex/regular_express.txt
你可以利用wget命令获取这个文档。
"Open Source" is a good mechanism to develop programs. apple is my favorite food. Football game is not use feet only. this dress doesn't fit me. However, this dress is about $ 3183 dollars. GNU is free air not free beer. Her hair is very beauty. I can't finish the test. Oh! The soup taste good. motorcycle is cheap than car. This window is clear. the symbol '*' is represented as start. Oh! My god! The gd software is a library for drafting programs. You are the best is mean you are the no. 1. The world <Happy> is the same with "glad". I like dog. google is the best tools for search keyword. goooooogle yes! go! go! Let's go. # I am VBird
Exp: 查找含有 test 或者 taste 的行
[volcanol@volcanol ~]$ grep -n --color=auto 't[ae]st' regular_express.txt 8:I can't finish the test. 9:Oh! The soup taste good.
这里我们可以看到第八行含有一个 test 字符序列, 与 t[ae]st 真好可以匹配一个; 而第九行 taste 也正好匹配一个,当然如果文档有如果
包含里 test 或者 tast 字符序列的那么也将会显示出来。如果要同时查找仅匹配: test 和 taste的字符串则需要将这个表达式进行修改:
[volcanol@volcanol ~]$ grep -n --color=auto 't[a-z]st' regular_express.txt | grep 't[ae]st[^a-df-z]' 8:I can't finish the test. 9:Oh! The soup taste good.
利用下面这个命令才能真正的找到test 或者 taste 。
我们可以测试一下:
[volcanol@volcanol ~]$ echo "i can't finish the testf" | grep -n --color=auto 't[a-z]st' | grep 't[ae]st[^a-df-z]' [volcanol@volcanol ~]$ echo "i can't finish the teste" | grep -n --color=auto 't[a-z]st' | grep 't[ae]st[^a-df-z]' 1:i can't finish the teste [volcanol@volcanol ~]$ echo "i can't finish the tastf" | grep -n --color=auto 't[a-z]st' | grep 't[ae]st[^a-df-z]'
可以发现第二个命令可以实现我们需要的功能。
【2】grep
grep是一个用来进行模式匹配的linux下的工具程序,通过这个工具可以进行数据的筛选。其命令如法如下:
SYNOPSIS
grep [OPTIONS] PATTERN [FILE...]
grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]
可以看到grep 有两种命令格式,一般用的比较多的是第一种。即: grep 选项 模式字符串 待查找的文件
这里还需要说明一点: 模式字符串可以用单引号,也可以用双引号, 在bash中,虽然单引号和双引号在某些时候存在一些区别;在进行
模式匹配的时候推荐使用单引号,以免引起一些副作用。例如在查询: “$SHELL” 时 ,“$SHELL” 和‘$SHELL’ 是不相同的。
我们在 regular_expression文件中的最后增加两行内容:
[volcanol@volcanol ~]$ cat regular_express.txt "Open Source" is a good mechanism to develop programs. apple is my favorite food. Football game is not use feet only. this dress doesn't fit me. However, this dress is about $ 3183 dollars. GNU is free air not free beer. Her hair is very beauty. I can't finish the test. Oh! The soup taste good. motorcycle is cheap than car. This window is clear. the symbol '*' is represented as start. Oh! My god! The gd software is a library for drafting programs. You are the best is mean you are the no. 1. The world <Happy> is the same with "glad". I like dog. google is the best tools for search keyword. goooooogle yes! go! go! Let's go. # I am VBird dido $SHELL /bin/bash
[volcanol@volcanol ~]$ grep --color=auto "$SHELL" regular_express.txt /bin/bash [volcanol@volcanol ~]$ grep --color=auto '$SHELL' regular_express.txt dido $SHELL
可以发现两个命令输出的结果不一样,下面我们利用grep 进行一些简单的测试。
Exp1: 获取所有含有 the 的行
[volcanol@volcanol ~]$ grep --color=auto 'the' regular_express.txt I can't finish the test. the symbol '*' is represented as start. You are the best is mean you are the no. 1. The world <Happy> is the same with "glad". google is the best tools for search keyword.
这里我们可以看到命令成功执行,每一个输出行都含有一个连续的字符序列: the
Exp:获取所有不含有 the 的行
[volcanol@volcanol ~]$ grep -nv 'the' regular_express.txt 1:"Open Source" is a good mechanism to develop programs. 2:apple is my favorite food. 3:Football game is not use feet only. 4:this dress doesn't fit me. 5:However, this dress is about $ 3183 dollars. 6:GNU is free air not free beer. 7:Her hair is very beauty. 9:Oh! The soup taste good. 10:motorcycle is cheap than car. 11:This window is clear. 13:Oh! My god! 14:The gd software is a library for drafting programs. 17:I like dog. 19:goooooogle yes! 20:go! go! Let's go. 21:# I am VBird 22:dido $SHELL 23:/bin/bash
在这里通过参数-v; 实现反向选择。
Exp: 不区分大小写来选取
grep 通过参数 -i 来实现不去很大小写。
8:I can't finish the test. 9:Oh! The soup taste good. 12:the symbol '*' is represented as start. 14:The gd software is a library for drafting programs. 15:You are the best is mean you are the no. 1. 16:The world <Happy> is the same with "glad". 18:google is the best tools for search keyword.
可以发现第14、16行的The 别选取了。
Exp: 输出结果,显示行号
通过参数-n 实现输出显示行号
[volcanol@volcanol ~]$ grep 'test' regular_express.txt I can't finish the test. [volcanol@volcanol ~]$ grep -n 'test' regular_express.txt 8:I can't finish the test.
可以发现,加上参数 -n 后,在输出的结果前面多了 8:
Exp:单字符通配
正则表达式的单字符通配与bash shell 的单字符通配存在一些不一样,在bash shell中非正则表达式通配符利用 ? 表示单字符通配; 而
正则表达式中单字符通配,利用 [ ] 来实现。
[volcanol@volcanol ~]$ grep -n 'ab[a-z]' regular_express.txt 5:However, this dress is about $ 3183 dollars.
如上命令,执行后,红色部分表示在文件中匹配的字符,这里利用 [a-z] 表示匹配 a-z 之间任意一个字符就算匹配成功, 因为模式字符串为
ab[a-z], 因此只要是 aba、abb、abc、.......aby、abz 中有一个匹配上就认为模式匹配成功,因此这里认为about 中的abo 匹配成功,因此输出
about所在的行。
Exp: 行首、行尾匹配限定
有时需要将匹配字符串限定在行首、行尾,这时可以使用行首限定 ^; 或者行尾限定$.
例如,我们仅能匹配行首匹配the的字符串,可以如下实现:
[volcanol@volcanol ~]$ grep -n '^the' regular_express.txt 12:the symbol '*' is represented as start.
可以看出只有 the 在行首匹配的这一行输出了。
如果我们想匹配 行尾的 d 字符的一行,可以如下实现:
[volcanol@volcanol ~]$ grep -n 'd$' regular_express.txt 21:# I am VBird
可以看出,只有最后一个字符是d的21行被选择输出了。
Exp: 注意方向选择行与排除字符在外,以及^符号作为行首和排除字符的区别。
当将^字符放在模式字符串的开头的时候,表示行首,当将^ 放在 [ ]中的时候表示排除,例如我们可以用下面的命令来表示空白行:
[volcanol@volcanol ~]$ grep -n '^$' regular_express.txt 24: 25:
可以发现文章的第24、25行是空白行。
这里小技巧我们可以利用cat 命令查看,空白行在linux中是怎么表示的:
cat -An regular_express.txt 1 "Open Source" is a good mechanism to develop programs.$ ........ 19 goooooogle yes!$ 20 go! go! Let's go.$ 21 # I am VBird$ 22 dido $SHELL$ 23 /bin/bash$ 24 $ 25 $
可以看到,在linux中,空白行只有$符号表示空白行,这个与Win有点不一样。
Exp: 任意字符 . 和重复字符 *
在正则表达式里,任意字符与通常的通配符不一样,在正则表达式里面,任意字符用 . 号表示,而用 * 号表示重复。例如:
[volcanol@volcanol ~]$ grep -n 'a.c' regular_express.txt 18:google is the best tools for search keyword.
如上所示,arc 就匹配里这个模式字符串 a.c ; 修改一下文件,然后在进行测试。
18:google is the best tools for search keyword. 25:///abc
可以发现 search 和 abc 这些都匹配了这个模式串。
那么 * 在正则表达式中又表示什么呢? * 表示重复。
[volcanol@volcanol ~]$ grep -n 'a.*c' regular_express.txt 1:"Open Source" is a good mechanism to develop programs. 10:motorcycle is cheap than car. 18:google is the best tools for search keyword. 25:///abc 26:////abdddc
可以看到这个模式匹配时,* 将结果放大里很多;因为这里表示将 * 前面的字符串可以重复匹配0到任意次。而 . 在* 前面,他匹配
任意字符,所以有了这个结果。我们还可以看一个别的测试:
[volcanol@volcanol ~]$ grep -n 'bd*c' regular_express.txt 25:///abc 26:////abdddc
第25行 匹配里 d 零次,而26行匹配里3次。
Exp: 指定重复次数
我们用* 表示重复任意次数,但是有时候我们仅需要重复有限的次数,这时我们可以利用 {} 来表示。但是因为{} 在这里是特殊字符
因此需要用 转义。
[volcanol@volcanol ~]$ grep -n 'bd{2,}c' regular_express.txt 26:////abdddc [volcanol@volcanol ~]$ grep -n 'bd{3,}c' regular_express.txt 26:////abdddc [volcanol@volcanol ~]$ grep -n 'bd{4,}c' regular_express.txt
这里我们可以看到,第一次表示匹配d字符2次或者2次以上,
第二个命令表示匹配d字符3次或者3次以上
第三个命令表示匹配d字符4次或者4次以上
如果我们需要指定重复次数的话可以这样来看:
[volcanol@volcanol ~]$ grep -n 'bd{2,4}c' regular_express.txt 26:////abdddc [volcanol@volcanol ~]$ grep -n 'bd{2,6}c' regular_express.txt 26:////abdddc
上面第一行表示重复2到4次,
第二个命令表示重复2到6次
小结:
在利用grep 这些工具的时候,一定要注意其处理时是支持正则表达式的,要注意与普通工具的差别,否则
将不能得到您想要的结果。