20171015老男孩第41期第6周课程中讲到了grep/egrep命令的四个选项:

1. -i 不区分大小写,即不区分:aA 

2. -w 按照单词 进行匹配(括号外的意思是老师讲的,但我总感觉这样理解起来有点疑惑,然后课下详细询问了一下老师-w选项的意义,然后自己总结了一下感觉好象应该叫做:全字符精确匹配/完全匹配)

3. -n 显示行号

4. -o 显示grep执行过程  grep正则把每次匹配到的内容显示出来

其中第1、3、4个选项很容易理解,但是第二个选项就有些不太容易理解了。下面我们通过试验来加深一下对-w这个选项的理解。

第一步:创建试验环境:

cat > test.txt <<EOF
I am oldboy teacher!
I teach linux.

I like badminton ball ,billiard ball and chinese chess!
my blog is http://oldboy.blog.51cto.com
our site is http://www.etiantian.org
my qq num is 49000448.

not 4900000448.
my god ,i am not oldbey,but OLDBOY!
EOF

第二步:使用-w选项,找出大于5位并且小于6位的字符串

[root@oldboyedu41-1 tmp]# egrep  -w '[a-z]{5,6}' test.txt 
I am oldboy teacher!
I teach linux.
I like badminton ball ,billiard ball and chinese chess!
my blog is http://oldboy.blog.51cto.com
my god ,i am not oldbey,but OLDBOY!
[root@oldboyedu41-1 tmp]# egrep -wo '[a-z]{5,6}' test.txt 
oldboy
teach
linux
chess
oldboy
oldbey
[root@oldboyedu41-1 tmp]# egrep -o '[a-z]{5,6}' test.txt 
oldboy
teache
teach
linux
badmin
billia
chines
chess
oldboy
etiant
oldbey

egrep -w '[a-z]{5,6}' test.txt    这条命令中,[a-z]代表取从小写的a到小写的z,{5,6}代表取最少5位,最多6位的字符串。

如果不加-w选项,就不是精确/完全匹配,而是即使某个字符串大于6位,也会取其中的6位做为符合条件的一项取值。

如果加上-w选项,则是只取>=5位,<=6位的字符串,超出这个范围的一律无视。


第三步:以一个简单的自制题目加深对-w选项的理解

题目:查找qq.txt文件中,填写正确的qq号。

创建试验环境:

cat >qq.txt <<EOF
02212345678
01012345678
123456789
14382730
11223344
12345
12345678
12000001
123
1234
01234567890
54321
654321
7654321
123456789123456789
12345678901234567890
EOF

分析:什么是正确的qq号?

一般情况下(暂时排除极端情况)正确的qq号至少应该符合两个最基本的条件:

  1. 非零开头:以零开头的一般是带区号的电话号码,比如010XXXXXXXX,022XXXXXXXX,这些要排除掉。

  2. 位数5-11位:qq号至少5位,目前最多11位。

那么这个题目其实就很简单了,第一步先排除掉以零开头的错误qq号:

[root@oldboyedu41-1 tmp]# grep -v "^0" qq.txt
123456789
14382730
11223344
12345
12345678
12000001
123
1234
54321
654321
7654321
123456789123456789
12345678901234567890

第二步取出>=5位并且<=11位的纯数字字符串

取纯数字使用[0-9]即可,取>=5位并且<=11位使用{5,11}即可。

[root@oldboyedu41-1 tmp]# grep -v "^0" qq.txt |egrep "[0-9]{5,11}" -n
1:123456789
2:14382730
3:11223344
4:12345
5:12345678
6:12000001
9:54321
10:654321
11:7654321
12:123456789123456789
13:12345678901234567890

这一步出现了一个问题(感谢陈哲同学提醒):大于11位的第12行和第13行也被取出来了。这是为什么呢?

使用-o选项看一下,到底取的是什么?

[root@oldboyedu41-1 tmp]# grep -v "^0" qq.txt |egrep "[0-9]{5,11}" -no
1:123456789
2:14382730
3:11223344
4:12345
5:12345678
6:12000001
9:54321
10:654321
11:7654321
12:12345678912
12:3456789
13:12345678901
13:234567890

原来第12行和第13行被分成了同时满足条件的两组字符串,被取了出来。这时就用到了-w这个选项。

[root@oldboyedu41-1 tmp]# grep -v "^0" qq.txt |egrep "[0-9]{5,11}" -nw
1:123456789
2:14382730
3:11223344
4:12345
5:12345678
6:12000001
9:54321
10:654321
11:7654321

搞定了!j_0057.gif

另外请教大神指点:grep -v "^0" qq.txt |egrep "[0-9]{5,11}" -nw  这条命令能否合并成一条命令?

望大神们不吝赐教,先谢过各路大神了j_0002.gif