7.2 正则表达式
借助grep学习基础正则表达式

本文描述了基础正则表达式的使用方法和操作实例。
准备工作
练习文件 sample.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.^M
GNU is free air not free beer.^M
Her hair is very beauty.^M
I can't finish the test.^M
Oh! The soup taste good.^M
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.^M
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 Bobby
实验过程
任务一:查找特定字符串
假设我们要从文件sample.txt当中取得the这个特定字符串,最简单的方式是:
grep -n 'the' sample.txt

如果想要反向选择呢,即当该行没有the这个字符串时才显示在屏幕上:
grep -vn 'the' sample.txt

-vn = -v -n
如果你想要获得不论大小写的the这个字符串,则执行:
grep -in 'the' sample.txt

任务二:中括号 [ ] 搜寻集合
STEP 1 集合
对比test或taste这两个单词可以发现,它们有共同点t?st存在。这个时候,可以这样来查寻:
grep -n 't[ae]st' sample.txt

在
[ae]这个集合中,有任意一个匹配上就可以,所以tast和test都符合要求
注意 [ ] 里面不论有几个字符,都只代表某一个字符,例如:

假如有一个字符串是
amme,它是不会被匹配的,因为ae中间有两个字符
STEP 2 反向选择
如果想要搜寻到有oo的字符时,则使用:
grep -n 'oo' sample.txt

如果不想要oo前面有“g”的行显示出来。此时,可以利用在[]集合字符中的反向选择[^]来完成:
grep -n '[^g]oo' sample.txt

注:^ 只有在
[ ]内部才是“否定”的意思,在其他场合是”行首“的意思

STEP 3 范围
假设oo前面不想有小写字母,可以这样写:[^abcd....xyz]oo。但是这样似乎不怎么方便,因此,我们可以将之简化:
grep -n '[^a-z]oo' sample.txt

a-z表示所有英文字符,如果要求数字与英文呢?那就将其全部写在一起,变成:[a-zA-Z0-9]。
例如,我们要获取有数字的那一行:
grep -n '[0-9]' sample.txt

由于考虑到语系对于编码顺序的影响,所以除了连续编码使用减号-之外,也可以使用如下的方法来取得前面两个测试的结果:
grep -n '[^[:lower:]]oo' sample.txt
grep -n '[[:digit:]]' sample.txt
例如丹麦语中,z不是最后一个字母
推荐做法: 用
[:lower:]代替a-z,注意不是代替[a-z]用[:upper:]代替A-Z用[:digit:]代替0-9
任务三:行首与行尾^$
STEP 1 行首
在前面,可以查询到一行字串里面有the,那如果想要让the 只在行首才列出呢?
grep -n '^the' sample.txt

如果想要开头是小写字母的那些行列出呢?可以这样写:
grep -n ^[a-z] sample.txt

思考:还可以怎么写? 提示:lower
如果不想要开头是英文字母,则可以这样:
grep -n '^[^a-zA-Z]' sample.txt

特别提示:“^”符号在字符集合符号
[]之内与之外的意义是不同的。在[]内代表“反向选择”,在[]之外则代表行首
STEP 2 行尾
反过来思考,如果想要找出行尾结束为小数点.的那些行,该如何处理?
grep -n '\.$' sample.txt

特别注意:因为小数点具有其他意义(下面会介绍),所以必须要使用跳转字节(\)来解除其特殊意义。
STEP 3 空白行
如果想要找出哪一行是空白行,即该行没有输入任何数据,该如何搜寻?
grep -n '^$' sample.txt

技巧:假设已经知道在一个程序脚本或者是配置文件中,空白行与开头为# 的那些行是注释,因此如果你要将数据打印出参考时,可以将这些数据省略掉以节省纸张,那么怎么操作呢?
以/etc/rsyslog.conf这个文件来作范例:
grep -v '^$' /etc/rsyslog.conf | grep -v '^#'

任务四:任意一个字符.与任意重复字符*
万用字符*可以用来代表任意(0或多个)字符,但是正则表示法并不是万用字符,两者之间是不相同的。至于正则表示法当中的.则代表“绝对有一个任意字符”的意思。这两个符号在正则表示法的意义如下。
- . (小数点):代表一个任意字符
- *(星号):代表重复前一个字符0次到无穷多次的意思,为组合形态

如果想要列出oo、ooo、oooo等数据,也就是说,至少要有两个(含)o以上,该如何操作呢?是o* 还是oo* 还是ooo* 呢?
因为
*代表的是“重复0个或多个前面的RE字符”,因此,o*代表的是“拥有空字符或一个o以上的字符”。
那如果是
oo*呢?则第一个o肯定必须要存在,第二个o则是可有可无的多个o, 所以,凡是含有o、oo、ooo、oooo等,都可以被列出来。
# 哪个可以匹配两个(含)o以上
grep -n 'goo*g' sample.txt
grep -n 'gooo*g' sample.txt

要找出以g开头且以g结尾的字符串,利用任意一个字符“.”,即“g.g”。因为“”可以是0个或多个重复前面的字符,而“.”是任意字节,所以“.*”就代表零个或多个任意字符。
grep -n 'g.*g' sample.txt
如果想要找出“任意数字”的行列呢?因为仅有数字,所以这样做:
grep -n '[0-9][0-9]*' sample.txt

这样写对吗?为什么?
grep -n '[0-9]*' sample.txt
任务五:限定连续字符范围{}
如果想要限制一个范围内的重复字符数该怎么办呢?举例来说,想要找出2个~5个o的连续字符串,该如何操作?
这时候就要使用限定范围的字符{}了。但因为{与}符号在Shell里是有特殊意义的,所以必须使用转义字符\来让其失去特殊意义才行。
先来做一个练习,假设要找到含两个o的字符串的行,可以这样做:
grep -n 'o\{2\}' sample.txt

似乎与ooo* 的字符没有什么差异,因为第19行有多个o依旧也出现了!
那么换个搜寻的字符串试试。假设要找出g后面接2~5个o,然后再接一个g的字符串,应该这样操作:
grep -n 'go\{2,5\}g' sample.txt

第19行没有被选中,因为19行有6个o
那么,如果想要的是2个o以上的goooo….g呢?除了可以使用gooo*g外,也可以这样:
grep -n 'go\{2,\}g' sample.txt

总结
| 字符 | 意义 | 范例 |
|---|---|---|
^word |
待搜寻的字串(word)在行首 | 搜寻行首为 # 开始的那一行 grep -n '^#' sample.txt |
word$ |
待搜寻的字串“word”在行尾 | 将行尾为 ! 的那一行列出来 grep -n '!$' sample.txt |
. |
代表一个任意字符(空格也算) | 搜寻eve eae eee e e,但不能仅有eegrep -n 'e.e' sample.txt |
\ |
转义字符,将特殊符号的特殊意义去除 | 搜寻含有单引号 ' 的那一行grep –n \' sample.txt |
* |
重复零个到无穷多个的前续字符 | 找出含有es ess esss等的字串。注意: *可以是0个字符所以es也符合要求 grep -n 'ess*' sample.txt |
[list] |
字符集合,里面列出想要筛选的字符 | 搜寻含有gl或gd的那一行注意: []仅代表一个字符例如 [afl]代表a或f或l的意思grep -n 'g[ld]' sample.txt |
[n1-n2] |
字符集合,里面列出想要筛选的字符范围 | 搜寻含有任意数字的那一行grep -n [0-9] sample.txt |
[^list] |
列出不需要的字符串或范围 | 搜寻oog ood,但不能是ootgrep -n 'oo[^t]' sample.txt |
\{n,m\} |
1. 连续n~m个的“前续字符” 2. {n} 是连续n个的前续字符 3. {n,} 是连续n个以上的前续字符 |
在g与g之间有2~3个的o,即goog、goooggrep -n 'go\{2,3\}g' sample.txt |
作业
练习文件:sample.txt(本手册开头提供内容)
基础题
- 查找所有包含字母"is"的行(不区分大小写),显示行号
- 找出所有以字母"t"或"T"开头的行
- 找出所有以点号".“结尾的行
- 找出所有包含数字的行
- 找出所有空白行和以#开头的行
进阶题
- 找出所有包含至少两个连续"o"的行
- 找出所有包含"g"开头和"g"结尾,中间包含2-4个"o"的行(如goog、gooog、goooog)
高级题
- 写一个命令,同时满足以下条件:
- 查找不以#开头的行
- 不显示空白行
- 行中必须包含数字
- 所有匹配都需要显示行号
- 写出至少两种不同的命令,实现以下功能:
- 查找所有行首是小写字母的行
- 解释每种方法的优缺点
要求
- 所有命令必须使用grep,并使用
-n参数显示行号 - 结果必须截图或完整粘贴命令输出