简介
grep一种文本字符查找工具,会以行为单位查找可以匹配字符的行,并且默认情况下显示整行。
我们所要做的就是:书写特定的字符,来匹配我们想要的内容。
字符分为两类: 一就是普通的字符,二是一种我们称之为‘元字符’的具有特殊意义的高上大字符。 而这种由普通字符或元字符所组合起来的,用于表达、匹配特定字符的字符串, 我们就称之为 “正则表达式”“正则表示法”等等... 正则表达有很多规范,这里只说grep用的, 因为别的也不会。
对了要注意一点: 元字符跟通配符是完全不同的两种表示方法, 通配符是bash提供的,而正则表示式却是一部分软件所提供的一种更加强大的字符串搜索功能。
正文
- 命令介绍
- 基本正则表达式
- 扩展的正则表达式
- POSIX字符组
- 后话
一、命令介绍
grep有两个扩展功能,分别用选项 -E ,-F 来启用。 而为了方便区分这两个功能,就又形成了另外两个命令, 分别是 egrep , fgrep. 一个是支持扩展的正则表达式,一个是只支持普通字符。
grep [options] ‘pattern’ [file,.....]
常用选项:
-v 显示没有匹配到的内容。
-o 只显示匹配到的字符,而不是整行。
-i 不区分大小写。 ignore-case.
-E 支持扩展的正则表达式。
-A # 同时显示匹配到的行的下边#行。
-B # 同时显示匹配到的行的上边#行。
-C # 同时显示匹配到的行的上下#行。
--color=auto 所匹配到的字符自动以颜色显示。
grep中想要匹配的内容,我们称之为 模式(pattern)。
这个命令支持管道 所以file数据可有可无。
二、基本正则表达式
以下这些都是元字符。正则表达式有很多规范, 我们只说linux的。
字符匹配:
. 点号 任意单个字符。
[] 指定里面的任意单个字符, 如: [acdb],a,c,d,b,这四个单字符都会匹配,
[^] 不匹配里面的任意单个字符。 跟上面完全相反,这四个单字符都不会匹配。
次数匹配:前面的字符的次数。
* 任意次前面的字符。前面的那个字符和*相当于是一体的,
.* 只是一种应用方法,代表任意个任意字符。
\? 前面字符的0次或1次。 0次相当于没有前面的字符, 次数匹配都是这样。
\{m\} 前面的字符的m次。
\{m,n\} 前面的字符的m-n次。 如: \{2,3\} 2-8次前面的字符。
\{m,\} 前面的字符至少m次。 没有上限,只有下限。
\{0,n\} 前面的字符至多只有n次。 有上限,下限是0个 就是前面的字符可有可无的。
位置锚定:用于指定字符出现的位置。
^ 指定行首
$ 指定行尾
^$ 这个只是一种应用方法, 代表空白行。 行首跟着行尾 空白行。
\<char 查找以字符开头的单词。 用 \b 也行。 \bchar 。 char是字符的意思。
char\> 查找以字符结尾的单词。 用\b 也行。 char\b
组:
\(\) 用于把单个字符组合成多个字符, 以组的方式再来次数匹配。 而且可以被引用。下边
\# 后向引用,也叫向后引用。
#为数字,可以引用第#个组的匹配结果,也就是第#个小括号,
注意引用的是组所匹配到的结果,而不是把组的功能都给复制过来。
下面列举一些例子让大家熟悉下规则:
1. 我们想要查找有 people 的行,不区分大小写。
[[email protected] ~]# grep --color=auto -i "people" text.tx
People in the park #看到了吗,People
[[email protected] ~]#
怎么样简单吧, 为了方便使用,下面的例子我就把--color选项直接加到grep的别名中了。
#alias grep=‘grep --color=auto‘
2. 尝试一下 . 这个小点的功能。 我们查找下以 f 开头,中间两个任意字符,以 m 结尾的都有哪些。
[[email protected] ~]# grep "f..m" text.tx
But from behind the walls of doubt
[[email protected] ~]#
3. 我记得第一个 要么是g 要么是m ,中间是两个一样的,结尾一个d,怎么查 [] \{m\}
还有 \{m,n\} .. 都是一样的意思,只不过是从几到几的一个范围,而不是指定几个。
[[email protected] ~]# grep "[gm].\{2\}d" text.tx
good morning everyone
I had a dream, I had an awesome dream
As we go down life‘s lonesome highway
[[email protected] ~]#
结果怎么是这样的呢, 这是因为 . 是任意字符, 而\{2\} 是代表2个前面的字符,也就是两个任意字符了,次数匹配也就这意思了。那么有没有办法让中间的一样呢,办法是有的,用组和后向引用,虽然感觉上有点大材小用。 \(\) \# 后向引用
[[email protected] ~]# grep "[gm]\(.\)\1d" text.tx
good morning everyone
[[email protected] ~]#
看看,我们要的是这个结果吧。 上面的意思就是 小括号里面的 . 所匹配到的是什么结果,后面\1也就是什么结果, 在个例子中,小括号是 o , 那么 \1 也就是 o.
4. 查找下行开头是A 或者 As 。 ^ \?
[[email protected] ~]# grep "^As\?" text.tx
And what they played
A voice was crying out
As we go down life‘s lonesome highway
[[email protected] ~]#
怎么样,了解乎。 \? 表示前面的字符可有可无。
5. 再查找个单词试试,way , 找这个单词,很简单吧, 那我们就来试试。
[[email protected] ~]# grep "way" text.tx
Say it for always
That‘s the way it should be
Say it for always
That‘s the way it should be
Say it for always
.........
[[email protected] ~]#
What? 搞什么仙人板板, 把有关way的字符串都给拉出来了。 那么 \< \>
[[email protected] ~]# grep "\<way\>" text.tx
That‘s the way it should be
That‘s the way it should be
When you feel you‘ve lost your way
That‘s the way it should be
That‘s the way it should be
[[email protected] ~]#
\< \> 指定单词用的, 这两个符号的两边只允许出现空格或者标点符号。
7. 查找以组为单位的重复字符。在这里是2到无限多个 组的次数匹配, \(\) \{m,\}
[[email protected] ~]# grep "\(way\)\{2,\}" text.tx
Say it for alway waywayway ways
[[email protected] ~]#
这个意思就是, 组 way, 重复两次到无限多次。
6. 再看看行尾是怎么回事, 查找行尾是 . 的,有意思吧,注意 . 可是元字符,意思就不用我说了吧, 那怎么让它变成普通字符, \ 转义字符, $
[[email protected] ~]# grep "\.$" text.tx
it‘s fine day today.
There are many birds flying in the sky.
[[email protected] ~]#
在里要说明一下这个转义字符是干什么用的呢 \ 。因为元字符里面也有的要用这个。
\ 的功能就是把有意义的字符,转成普通的。 把有意义的普通字符转成有意义的, 当然如果是彻彻底底的普通字符,再转也没用。
打个比喻吧, 就好像 变形金刚一样, 看着是普通车,但他是大机器人, 看他是大机器人,也可以变成车, 如果真是破车,那也变不了。
而在正则表达式里的加\的元字符, 是因为规范的问题所导致的, 在grep所用的正则表达式里,那些加\的元字符,都是普通字符, 需要加上\来转义,来变形, 不加的话,它就是普通字符。
而在egrep 所用的扩展的正则表达式中, 除了\< \>和后向引用 还要用转义外, 其它的都不要用转义了,
这又是另外的一种规范, 如果非要加转义符, 反而又变成普通字符了。 废话就不说了,看看扩展的正则表达式。
三、扩展的正则表达式
元字符:
. 任意单个字符
[] 范围内的任意单个字符
[^] 范围外的任意单个字符
次数匹配:
* 匹配任意次前面的字符
? 匹配0或1次前面的字符
+ 匹配至少1次前面的字符。
{m} 匹配其前面的字符m次。
{m,n} 匹配其前面的字符m-n次。
{m,} 匹配其前面的字符至少m次。
{0,n} 至多1次。
位置锚定:
^ 行首
$ 行尾
\< 或 \b 词首
\> 或 \b 词尾
分组:
() 分组
| 或者, 词组的或,两边的词组。
(|) 中括号中的或者。 可以自己指定。
除了有的转义字符没有了外,还加了几个不同的元字符。 下面说明一下:
+ 我想朋友们看上面的字符介绍,应该也明白了吧。
* 前面的字符 从0到无限多个, 0代表没有。
而 + 是从1到无限多个。 这个例子就不列了。
关于 | 和 (|) 还有
1. 找到say 或者 for 或者 way 。
[[email protected] ~]# egrep --color=auto -i "say|for|way" text.tx
Say You Say Me
For you and for me
Say you, say me
Say it for alway waywayway ways
That‘s the way, it should be
Say you, say me
........
因为是扩展的正则表达式,所以要用egrep 或者 是 grep -E。
这个例子这个样子的查找还可以, 如果要查找开头是某某字符,中间可能是这三个,就不行了。 因为把字符加在前面,就是前面那一串字符的了,跟后面的没有关系。
2. 那好吧,查找行首以you开头的 say for way. ^ .* (|)
[[email protected] ~]# egrep --color=auto -i "^you.*(say|for|way)" text.tx
You‘ve got someone there to say
[[email protected] ~]#
因为匹配了 .* 这可是代表任意个任意字符啊。 所以, you 在行首, say在行尾,中间都匹配给了.*了。 虽然只匹配了一行, 不过意思也就是这个样子。
3. 对歌词作者说声: Sorry , 把这么好的歌词给改的千疮百孔。
[[email protected] ~]# egrep --color=auto -i "(say|for).*\1" text.tx
Say You Say Me
For you and for me
Say you, say me
Say you, say me
Say you, say me
Say you, say me
Say you, say me
Say you, say me
Say you, say me
Say you, say me
[[email protected] ~]#
这个也是组加后向引用, 后向引用只匹配前面组里的结果, 前面匹配到say,后面也就是say. for也是一样。
四、POSIX字符组,代表某些特定的字符, 这里只列出一部分常用的。
[:upper:] 大写字母 [:lower:] 小写字母
[:alpha:] 所有字母 [:digit:] 所有数字
[:alnum:] 所有字母和数字 [:space:] 空格
[:punct:] 标点符号
Linux/Unix下的POSIX规范 这里说明了一些 POSIX字符组和正则表达式的一些规范。
[:upper:] = A-Z 不过更规范,不容易出现字符匹配错误。
[:upper:] 这是一个固定的格式,等于A-Z 如果要匹配它,还要加上 []
如: 开头大写字母,加ay
[[email protected] ~]# grep "[[:upper:]]ay" text.tx
Say You Say Me
Say you, say me
Say it for alway waywayway ways
Say you, say me
Say it together, naturally
Say you, say me
.......
开头不是大写字母,加ay
[[email protected] ~]# grep "[^[:upper:]]ay" text.tx
123ay
0ay
;ay
.ay
it‘s fine day today.
Say you, say me
Playing game in the dark
至于其它的意思都一样, 只是代表某一组字符。
五、后话
呼,可算是写完了, 越写越心烦啊, 可能是因为写的太少了吧,真是得要多练练。
这种文章网上已经是多如牛毛,所以我也不指望能多帮助大家,只是略尽绵力,
同时也是锻炼下自己,文中如有错误或者问题,还请朋友们指出。
grep 文本查找工具