linux下的orre命令,鸟哥的 Linux 私房菜 -- 正规表示法 (regular expression, RE) 与文件格式化处理...

要了解正规表示法最简单的方法就是由实际练习去感受啦!所以在汇整正规表示法特殊符号前,

我们先以底下这个文件的内容来进行正规表示法的理解吧!先说明一下,底下的练习大前提是:

语系已经使用『 export LANG=C 』的配置值;

grep 已经使用 alias 配置成为『 grep --color=auto 』

至於本章的练习用文件请由底下的连结来下载。需要特别注意的是,底下这个文件是鸟哥在 MS Windows 系统下编辑的,

并且已经特殊处理过,因此,他虽然是纯文字档,但是内含一些 Windows

系统下的软件常常自行加入的一些特殊字节,例如断行字节 (^M) 就是一例!

所以,你可以直接将底下的文字以 vi 储存成 regular_express.txt 这个文件,

不过,还是比较建议直接点底下的连结:

如果你的 Linux 可以直接连上 Internet 的话,那么使用如下的命令来捉取即可:

wget http://cn.linux.vbird.org/linux_basic/0330regularex/regular_express.txt

至於这个文件的内容如下:

[root@www ~]# vi 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.^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 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

这文件共有 22 行,最底下一行为空白行!现在开始我们一个案例一个案例的来介绍吧!

例题一、搜寻特定字串

搜寻特定字串很简单吧?假设我们要从刚刚的文件当中取得 the 这个特定字串,最简单的方式就是这样:

[root@www ~]# grep -n 'the' regular_express.txt

8:I can't finish the test.

12:the symbol '*' is represented as start.

15:You are the best is mean you are the no. 1.

16:The world is the same with "glad".

18:google is the best tools for search keyword.

那如果想要『反向选择』呢?也就是说,当该行没有

'the' 这个字串时才显示在萤幕上,那就直接使用:

[root@www ~]# grep -vn 'the' regular_express.txt

你会发现,萤幕上出现的行列为除了 8,12,15,16,18 五行之外的其他行列!

接下来,如果你想要取得不论大小写的 the 这个字串,则:

[root@www ~]# grep -in 'the' regular_express.txt

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 is the same with "glad".

18:google is the best tools for search keyword.

除了多两行 (9, 14行) 之外,第 16 行也多了一个 The 的关键字被撷取到喔!

例题二、利用中括号 [] 来搜寻集合字节

如果我想要搜寻 test 或 taste 这两个单字时,可以发现到,其实她们有共通的 't?st'

存在~这个时候,我可以这样来搜寻:

[root@www ~]# grep -n 't[ae]st' regular_express.txt

8:I can't finish the test.

9:Oh! The soup taste good.

了解了吧?其实 [] 里面不论有几个字节,他都谨代表某『一个』字节,

所以,上面的例子说明了,我需要的字串是『tast』或『test』两个字串而已!

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

[root@www ~]# grep -n 'oo' 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.

9:Oh! The soup taste good.

18:google is the best tools for search keyword.

19:goooooogle yes!

但是,如果我不想要 oo 前面有 g 的话呢?此时,可以利用在集合字节的反向选择 [^] 来达成:

[root@www ~]# grep -n '[^g]oo' regular_express.txt

2:apple is my favorite food.

3:Football game is not use feet only.

18:google is the best tools for search keyword.

19:goooooogle yes!

意思就是说,我需要的是 oo ,但是 oo 前面不能是 g 就是了!仔细比较上面两个表格,你会发现,第

1,9 行不见了,因为 oo 前面出现了 g 所致!第 2,3 行没有疑问,因为 foo 与 Foo 均可被接受!但是第 18

行明明有 google 的 goo 啊~别忘记了,因为该行后面出现了 tool 的 too 啊!所以该行也被列出来~

也就是说, 18 行里面虽然出现了我们所不要的项目 (goo) 但是由於有需要的项目 (too) ,

因此,是符合字串搜寻的喔!

至於第 19 行,同样的,因为 goooooogle 里面的 oo 前面可能是 o ,例如:

go(ooo)oogle ,所以,这一行也是符合需求的!

再来,假设我 oo 前面不想要有小写字节,所以,我可以这样写 [^abcd....z]oo ,

但是这样似乎不怎么方便,由於小写字节的 ASCII 上编码的顺序是连续的,

因此,我们可以将之简化为底下这样:

[root@www ~]# grep -n '[^a-z]oo' regular_express.txt

3:Football game is not use feet only.

也就是说,当我们在一组集合字节中,如果该字节组是连续的,例如大写英文/小写英文/数字等等,

就可以使用[a-z],[A-Z],[0-9]等方式来书写,那么如果我们的要求字串是数字与英文呢?

呵呵!就将他全部写在一起,变成:[a-zA-Z0-9]。例如,我们要取得有数字的那一行,就这样:

[root@www ~]# grep -n '[0-9]' regular_express.txt

5:However, this dress is about $ 3183 dollars.

15:You are the best is mean you are the no. 1.

但由於考虑到语系对於编码顺序的影响,因此除了连续编码使用减号『 - 』之外,

你也可以使用如下的方法来取得前面两个测试的结果:

[root@www ~]# grep -n '[^[:lower:]]oo' regular_express.txt

# 那个 [:lower:] 代表的就是 a-z 的意思!请参考前两小节的说明表格

[root@www ~]# grep -n '[[:digit:]]' regular_express.txt

这样对於 [] 以及 [^] 以及 [] 当中的 - ,还有关於前面表格提到的特殊关键字有了解了吗?^_^!

例题三、行首与行尾字节 ^ $

我们在例题一当中,可以查询到一行字串里面有 the 的,那如果我想要让 the 只在行首列出呢?

这个时候就得要使用定位字节了!我们可以这样做:

[root@www ~]# grep -n '^the' regular_express.txt

12:the symbol '*' is represented as start.

此时,就只剩下第 12 行,因为只有第 12 行的行首是 the 开头啊~此外,

如果我想要开头是小写字节的那一行就列出呢?可以这样:

[root@www ~]# grep -n '^[a-z]' regular_express.txt

2:apple is my favorite food.

4:this dress doesn't fit me.

10:motorcycle is cheap than car.

12:the symbol '*' is represented as start.

18:google is the best tools for search keyword.

19:goooooogle yes!

20:go! go! Let's go.

你可以发现我们可以捉到第一个字节都不是大写的!只不过 grep 列出的关键字部分不只有第一个字节,

grep 是列出一整个字 (word) 说!同样的,上面的命令也可以用如下的方式来取代的:

[root@www ~]# grep -n '^[[:lower:]]' regular_express.txt

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

[root@www ~]# grep -n '^[^a-zA-Z]' regular_express.txt

1:"Open Source" is a good mechanism to develop programs.

21:# I am VBird

# 命令也可以是: grep -n '^[^[:alpha:]]' regular_express.txt

注意到了吧?那个 ^ 符号,在字节集合符号(括号[])之内与之外是不同的!

在 [] 内代表『反向选择』,在 [] 之外则代表定位在行首的意义!要分清楚喔!

反过来思考,那如果我想要找出来,行尾结束为小数点 (.) 的那一行,该如何处理:

[root@www ~]# grep -n '\.$' 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.

10:motorcycle is cheap than car.

11:This window is clear.

12:the symbol '*' is represented as start.

15:You are the best is mean you are the no. 1.

16:The world is the same with "glad".

17:I like dog.

18:google is the best tools for search keyword.

20:go! go! Let's go.

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

不过,你或许会觉得奇怪,但是第 5~9 行最后面也是 . 啊~怎么无法列印出来?

这里就牵涉到 Windows 平台的软件对於断行字节的判断问题了!我们使用 cat -A 将第五行拿出来看,

你会发现:

[root@www ~]# cat -An regular_express.txt | head -n 10 | tail -n 6

5 However, this dress is about $ 3183 dollars.^M$

6 GNU is free air not free beer.^M$

7 Her hair is very beauty.^M$

8 I can't finish the test.^M$

9 Oh! The soup taste good.^M$

10 motorcycle is cheap than car.$

我们在第十章内谈到过断行字节在 Linux 与 Windows 上的差异,

在上面的表格中我们可以发现 5~9 行为 Windows 的断行字节 (^M$) ,而正常的 Linux 应该仅有第 10 行显示的那样 ($)

。所以罗,那个 . 自然就不是紧接在 $ 之前喔!也就捉不到 5~9 行了!这样可以了解 ^ 与 $ 的意义吗?

好了,先不要看底下的解答,自己想一想,那么如果我想要找出来,哪一行是『空白行』,

也就是说,该行并没有输入任何数据,该如何搜寻?

[root@www ~]# grep -n '^$' regular_express.txt

22:

因为只有行首跟行尾 (^$),所以,这样就可以找出空白行啦!再来,假设你已经知道在一个程序脚本

(shell script) 或者是配置档当中,空白行与开头为 # 的那一行是注解,因此如果你要将数据列出给别人参考时,

可以将这些数据省略掉以节省保贵的纸张,那么你可以怎么作呢?

我们以 /etc/syslog.conf 这个文件来作范例,你可以自行参考一下输出的结果:

[root@www ~]# cat -n /etc/syslog.conf

# 在 CentOS 中,结果可以发现有 33 行的输出,很多空白行与 # 开头

[root@www ~]# grep -v '^$' /etc/syslog.conf | grep -v '^#'

# 结果仅有 10 行,其中第一个『 -v '^$' 』代表『不要空白行』,

# 第二个『 -v '^#' 』代表『不要开头是 # 的那行』喔!

是否节省很多版面啊?

例题四、任意一个字节 . 与重复字节 *

在第十一章 bash 当中,我们知道万用字节 * 可以用来代表任意(0或多个)字节,

但是正规表示法并不是万用字节,两者之间是不相同的!

至於正规表示法当中的『 . 』则代表『绝对有一个任意字节』的意思!这两个符号在正规表示法的意义如下:

. (小数点):代表『一定有一个任意字节』的意思;

* (星星号):代表『重复前一个字节, 0 到无穷多次』的意思,为组合形态

这样讲不好懂,我们直接做个练习吧!假设我需要找出 g??d 的字串,亦即共有四个字节,

起头是 g 而结束是 d ,我可以这样做:

[root@www ~]# grep -n 'g..d' regular_express.txt

1:"Open Source" is a good mechanism to develop programs.

9:Oh! The soup taste good.

16:The world is the same with "glad".

因为强调 g 与 d 之间一定要存在两个字节,因此,第 13 行的 god 与第 14 行的 gd

就不会被列出来啦!再来,如果我想要列出有 oo, ooo, oooo 等等的数据,

也就是说,至少要有两个(含) o 以上,该如何是好?是 o* 还是 oo* 还是 ooo* 呢?

虽然你可以试看看结果, 不过结果太占版面了 @_@ ,所以,我这里就直接说明。

因为 * 代表的是『重复 0 个或多个前面的 RE 字符』的意义,

因此,『o*』代表的是:『拥有空字节或一个 o 以上的字节』,

特别注意,因为允许空字节(就是有没有字节都可以的意思),因此,『 grep -n 'o*' regular_express.txt 』将会把所有的数据都列印出来萤幕上!

那如果是『oo*』呢?则第一个 o 肯定必须要存在,第二个 o 则是可有可无的多个 o ,

所以,凡是含有 o, oo, ooo, oooo 等等,都可以被列出来~

同理,当我们需要『至少两个 o 以上的字串』时,就需要 ooo* ,亦即是:

[root@www ~]# grep -n 'ooo*' 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.

9:Oh! The soup taste good.

18:google is the best tools for search keyword.

19:goooooogle yes!

这样理解 * 的意义了吗?好了,现在出个练习,如果我想要字串开头与结尾都是 g,但是两个 g

之间仅能存在至少一个 o ,亦即是 gog, goog, gooog.... 等等,那该如何?

[root@www ~]# grep -n 'goo*g' regular_express.txt

18:google is the best tools for search keyword.

19:goooooogle yes!

如此了解了吗?再来一题,如果我想要找出 g 开头与 g 结尾的字串,当中的字节可有可无,那该如何是好?是『g*g』吗?

[root@www ~]# grep -n 'g*g' regular_express.txt

1:"Open Source" is a good mechanism to develop programs.

3:Football game is not use feet only.

9:Oh! The soup taste good.

13:Oh! My god!

14:The gd software is a library for drafting programs.

16:The world is the same with "glad".

17:I like dog.

18:google is the best tools for search keyword.

19:goooooogle yes!

20:go! go! Let's go.

但测试的结果竟然出现这么多行?太诡异了吧?其实一点也不诡异,因为 g*g 里面的 g* 代表『空字节或一个以上的 g』

在加上后面的 g ,因此,整个 RE 的内容就是 g, gg, ggg, gggg ,

因此,只要该行当中拥有一个以上的 g 就符合所需了!

那该如何得到我们的 g....g 的需求呢?呵呵!就利用任意一个字节『.』啊!

亦即是:『g.*g』的作法,因为 * 可以是 0 或多个重复前面的字符,而 . 是任意字节,所以:

『.* 就代表零个或多个任意字节』的意思啦!

[root@www ~]# grep -n 'g.*g' regular_express.txt

1:"Open Source" is a good mechanism to develop programs.

14:The gd software is a library for drafting programs.

18:google is the best tools for search keyword.

19:goooooogle yes!

20:go! go! Let's go.

因为是代表 g 开头与 g 结尾,中间任意字节均可接受,所以,第 1, 14, 20 行是可接受的喔!

这个 .* 的 RE 表示任意字节是很常见的,希望大家能够理解并且熟悉!

再出一题,如果我想要找出『任意数字』的行列呢?因为仅有数字,所以就成为:

[root@www ~]# grep -n '[0-9][0-9]*' regular_express.txt

5:However, this dress is about $ 3183 dollars.

15:You are the best is mean you are the no. 1.

虽然使用 grep -n '[0-9]' regular_express.txt 也可以得到相同的结果,

但鸟哥希望大家能够理解上面命令当中 RE 表示法的意义才好!

例题五、限定连续 RE 字符范围 {}

在上个例题当中,我们可以利用 . 与 RE 字符及 * 来配置 0 个到无限多个重复字节,

那如果我想要限制一个范围区间内的重复字节数呢?举例来说,我想要找出两个到五个 o

的连续字串,该如何作?这时候就得要使用到限定范围的字符 {} 了。

但因为 { 与 } 的符号在 shell 是有特殊意义的,因此,

我们必须要使用跳脱字符 \ 来让他失去特殊意义才行。

至於 {} 的语法是这样的,假设我要找到两个 o 的字串,可以是:

[root@www ~]# grep -n 'o\{2\}' 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.

9:Oh! The soup taste good.

18:google is the best tools for search keyword.

19:goooooogle yes!

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

好,那么换个搜寻的字串,假设我们要找出 g 后面接 2 到 5 个 o ,然后再接一个 g 的字串,他会是这样:

[root@www ~]# grep -n 'go\{2,5\}g' regular_express.txt

18:google is the best tools for search keyword.

嗯!很好!第 19 行终於没有被取用了(因为 19 行有 6 个 o 啊!)。

那么,如果我想要的是 2 个 o 以上的 goooo....g 呢?除了可以是 gooo*g ,也可以是:

[root@www ~]# grep -n 'go\{2,\}g' regular_express.txt

18:google is the best tools for search keyword.

19:goooooogle yes!

呵呵!就可以找出来啦~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值