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 ,但不能仅有ee grep -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 ,但不能是oot grep -n 'oo[^t]' sample.txt |
\{n,m\} |
1. 连续n~m个的“前续字符” 2. {n} 是连续n个的前续字符 3. {n,} 是连续n个以上的前续字符 |
在g与g之间有2~3个的o,即goog 、gooog grep -n 'go\{2,3\}g' sample.txt |
作业
练习文件:sample.txt(本手册开头提供内容)
基础题
- 查找所有包含字母"is"的行(不区分大小写),显示行号
- 找出所有以字母"t"或"T"开头的行
- 找出所有以点号".“结尾的行
- 找出所有包含数字的行
- 找出所有空白行和以#开头的行
进阶题
- 找出所有包含至少两个连续"o"的行
- 找出所有包含"g"开头和"g"结尾,中间包含2-4个"o"的行(如goog、gooog、goooog)
高级题
- 写一个命令,同时满足以下条件:
- 查找不以#开头的行
- 不显示空白行
- 行中必须包含数字
- 所有匹配都需要显示行号
- 写出至少两种不同的命令,实现以下功能:
- 查找所有行首是小写字母的行
- 解释每种方法的优缺点
要求
- 所有命令必须使用grep,并使用
-n
参数显示行号 - 结果必须截图或完整粘贴命令输出