7.2 正则表达式

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

系列 - LINUX VIM和Shell基础

本文描述了基础正则表达式的使用方法和操作实例。

练习文件 sample.txt 的文件内容:

text

"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这个特定字符串,最简单的方式是:

bash

grep -n 'the' sample.txt

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

bash

grep -vn 'the' sample.txt

-vn = -v -n

如果你想要获得不论大小写the这个字符串,则执行:

bash

grep -in 'the' sample.txt

STEP 1 集合

对比testtaste这两个单词可以发现,它们有共同点t?st存在。这个时候,可以这样来查寻:

bash

grep -n 't[ae]st' sample.txt

[ae]这个集合中,有任意一个匹配上就可以,所以tasttest都符合要求

注意 [ ] 里面不论有几个字符,都只代表某一个字符,例如:

假如有一个字符串是amme ,它是不会被匹配的,因为ae中间有两个字符

STEP 2 反向选择

如果想要搜寻到有oo的字符时,则使用:

bash

grep -n 'oo' sample.txt

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

bash

grep -n '[^g]oo' sample.txt

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

STEP 3 范围

假设oo前面不想有小写字母,可以这样写:[^abcd....xyz]oo。但是这样似乎不怎么方便,因此,我们可以将之简化:

bash

grep  -n  '[^a-z]oo'  sample.txt

a-z表示所有英文字符,如果要求数字与英文呢?那就将其全部写在一起,变成:[a-zA-Z0-9]

例如,我们要获取有数字的那一行:

bash

grep  -n  '[0-9]'  sample.txt

由于考虑到语系对于编码顺序的影响,所以除了连续编码使用减号-之外,也可以使用如下的方法来取得前面两个测试的结果:

bash

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 只在行首才列出呢?

bash

grep -n '^the' sample.txt

如果想要开头是小写字母的那些行列出呢?可以这样写:

bash

grep -n ^[a-z] sample.txt

思考:还可以怎么写? 提示:lower

如果不想要开头是英文字母,则可以这样:

bash

grep  -n  '^[^a-zA-Z]' sample.txt

特别提示:“^”符号在字符集合符号[]之内与之外的意义是不同的。在 [] 代表“反向选择”,在 [] 之外则代表行首

STEP 2 行尾

反过来思考,如果想要找出行尾结束为小数点.的那些行,该如何处理?

bash

grep  -n  '\.$' sample.txt

特别注意:因为小数点具有其他意义(下面会介绍),所以必须要使用跳转字节(\)来解除其特殊意义。

STEP 3 空白行

如果想要找出哪一行是空白行,即该行没有输入任何数据,该如何搜寻?

bash

grep  -n  '^$'  sample.txt

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

/etc/rsyslog.conf这个文件来作范例:

bash

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等,都可以被列出来。

bash

# 哪个可以匹配两个(含)o以上
grep  -n  'goo*g'  sample.txt
grep  -n  'gooo*g'  sample.txt

要找出以g开头且以g结尾的字符串,利用任意一个字符“.”,即“g.g”。因为“”可以是0个或多个重复前面的字符,而“.”是任意字节,所以“.*”就代表零个或多个任意字符。

bash

grep -n 'g.*g' sample.txt

如果想要找出“任意数字”的行列呢?因为仅有数字,所以这样做:

bash

grep -n '[0-9][0-9]*' sample.txt

这样写对吗?为什么?

bash

grep -n '[0-9]*' sample.txt

如果想要限制一个范围内的重复字符数该怎么办呢?举例来说,想要找出2个~5个o的连续字符串,该如何操作?

这时候就要使用限定范围的字符{}了。但因为{}符号在Shell里是有特殊意义的,所以必须使用转义字符\来让其失去特殊意义才行。

先来做一个练习,假设要找到含两个o的字符串的行,可以这样做:

bash

grep -n 'o\{2\}' sample.txt

似乎与ooo* 的字符没有什么差异,因为第19行有多个o依旧也出现了!

那么换个搜寻的字符串试试。假设要找出g后面接2~5个o,然后再接一个g的字符串,应该这样操作:

bash

grep -n 'go\{2,5\}g' sample.txt

第19行没有被选中,因为19行有6个o

那么,如果想要的是2个o以上的goooo….g呢?除了可以使用gooo*g外,也可以这样:

bash

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] 字符集合,里面列出想要筛选的字符 搜寻含有glgd的那一行
注意[]仅代表一个字符
例如[afl]代表afl的意思
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,即googgooog
grep -n 'go\{2,3\}g' sample.txt

练习文件:sample.txt(本手册开头提供内容)

  1. 查找所有包含字母"is"的行(不区分大小写),显示行号
  2. 找出所有以字母"t"或"T"开头的行
  3. 找出所有以点号".“结尾的行
  4. 找出所有包含数字的行
  5. 找出所有空白行和以#开头的行
  1. 找出所有包含至少两个连续"o"的行
  2. 找出所有包含"g"开头和"g"结尾,中间包含2-4个"o"的行(如goog、gooog、goooog)
  1. 写一个命令,同时满足以下条件:
    • 查找不以#开头的行
    • 不显示空白行
    • 行中必须包含数字
    • 所有匹配都需要显示行号
  2. 写出至少两种不同的命令,实现以下功能:
    • 查找所有行首是小写字母的行
    • 解释每种方法的优缺点
  1. 所有命令必须使用grep,并使用-n参数显示行号
  2. 结果必须截图或完整粘贴命令输出

在线正则表达式可视化测试工具