egrep和egrep的正则表达式
程序员文章站
2022-06-29 21:55:57
...
egrep 和 grep
- grep(Global search REgular expression and Prind out the line)全称就叫全面搜索正则表达式 并打印行出来,本文测试使用的grep的版本是Ubuntu18.04预装的,grep版本如下:
aaa@qq.com:~$ grep --version
grep (GNU grep) 3.1
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Mike Haertel and others, see <http://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>.
- egrep实际上是grep的增强版,拓展了grep对正则表达式的支持,许多系统中”egrep”等价于”grep -E”,日常使用中能用egrep的情况就应该选择使用egrep,功能更加的强大。
aaa@qq.com:~$ cat /bin/egrep
#!/bin/sh
exec grep -E "aaa@qq.com"
- 使用方法如下所示,-i是grep的选项,表示忽略大小写,而grep中通常用单引号来包围正则表达式,而egrep所支持的正则表达式将是接下来讨论的重点,剩下email.txt则是grep查找的文件。
Usage:
grep [OPTION]... PATTERN [FILE]...
eg:
egrep -i '^(from|subject):' email.txt
option 选项
‘grep –help’可以获取想知道的帮助,这里举几个比较常用的选项
-n : 打印行号,找代码的时候很方便
-r : 递归的查找目录下所有文件
-v : 反转查找(打印出不匹配的行)
-i : 忽略大小写
-c : 计算匹配行的行数
-A, --after-context=NUM : 打印匹配行和之后的NUM行
-B, --before-context=NUM : 打印匹配行和之前的NUM行
-C, --context=NUM : 打印匹配行和前后各NUM行
egrep中的正则表达式
元字符的介绍
虽然不同流派的正则表达式中,正则表达式的语法会有不同,而且不同版本的egrep对正则表达式的支持也不尽相同,但是通用的知识也很多,对于一般的需求,熟悉一个流派之后,其他的流派只是多试几次,也可以很快上手。
- 行的开始和结束
‘^’表示行的开始,’$’表示行的结束,
'^cat' : 匹配首字母为'c',紧接着是'a',接下来是't'的行(正则表达式应该以字符为单位进行理解)
'^$' : 行开头紧接着行结尾,实际上就是匹配空行
'^' : 没有意义,每行都能匹配
- 字符组
使用者列举出所有希望匹配的字符集合称为字符组,使用方法是将希望的匹配的字符用’[]’包围起来。
'[-ea]' : 匹配一个字符,e或者a或者字符'-'
'[0-9A-Z]' : 匹配0-9或A-Z之间的任意一个字符,顺序无关('-'表示范围,放在行首则只表示普通字符)
eg:
jackson@ubuntu:~$ cat -n tt.txt
1 Python
2 Hello Java
3 hello java ! hello world
4 C++
5 C
6 PHP is the best
7 C#
jackson@ubuntu:~$ egrep '[Jj]ava' tt.txt
Hello Java
hello java ! hello world
- 排除性字符组
在字符组的最前面加上’^’表示排除的意思,需要注意的是egre会在检查正则表达式之前就把换行符给去除,如下面的例子,’Python[^u]’能够匹配第二行却没法匹配第一行。
'[^2-6]' : 表示匹配除了2-6之外的其他字符
eg:
jackson@ubuntu:~$ cat -n tt.txt
1 Python
2 Python OK
jackson@ubuntu:~$ egrep 'Python[^u]' tt.txt
Python OK
- 多选结构
’|’用来连接组合多个正则表达式,表示“或者”,比如说之前举的例子’[Jj]ava’就等价于’Java|java’,也可以写成’(J|j)ava’。
注意:
一个字符组只能匹配目标文本中的单个字符,而多选结构自身就是完整的正则的表达式,可以匹配任意长度的文本。 - 单词分界符
当需要匹配一个单词的时候,就需要用到单词分界符了’\<’和’\>’,解释好像不太清楚可以直接看看下面的例子就明白了,不过这个功能不是所有的egrep的版本都会支持,另外egrep中单独的’<’和’>’并没有特殊含义,只有与’\’连接时才有特殊含义。另外egrep并没有智能到认识英文单词,只是简单的匹配它认为的单词(包括数字)开头(‘\<’)与结尾(‘\>’),比如说
jackson@ubuntu:~$ egrep 'Python0' tt.txt
test Python0 OK
test aPython0 OK
test Python0a OK
jackson@ubuntu:~$ egrep '\<Python0\>' tt.txt
test Python0 OK
- 匹配任意字符
’.’能够匹配任意的单字符,当我们的正则表达式中只是需要一个占位符而不在意这个位子到底是什么字符时使用。
jackson@ubuntu:~$ cat ttt.txt
2018-08-12
2018/08/12
2018.08.12
jackson@ubuntu:~$ egrep '2018.08.12' ttt.txt # 这里的'.'表示通配符代表任意字符
2018-08-12
2018/08/12
2018.08.12
jackson@ubuntu:~$ egrep '2018\.08\.12' ttt.txt # 这里的'\.'表示普通字符'.'
2018.08.12
- 量词
元字符 | 次数下限 | 次数上限 | 含义 |
---|---|---|---|
? | 无 | 1 | 前一个字符出现一次或者0次 |
* | 无 | 无 | 前一个字符出现任意次数 |
+ | 1 | 无 | 前一个字符至少出现1次(可以出现任意多次) |
除了上述的几个量词之外,有些egrep还会支持区间量词,用法’…{min,max}’,表示前面一个元字符出现min~max次。下面这个例子,’-i’前面已经说到过,表示egrep不区分大小写的匹配,’?’表示前面的’a’字符出现0次或者1次,’()’作用是将’java?’合并成一个单元,’{3,5}’表示前面的这个单元出现3到5次,当然也支持类似’{3,}’和’{,5}’的语法,分别表示出现3到无穷次和出现0到5次。
jackson@ubuntu:~$ cat tt.txt
javaJavaJAVAJava
javaJavTJAVA
javaJavaJAVJavjAv
javaJava
jackson@ubuntu:~$ egrep -i '(java?){3,5}' tt.txt
javaJavaJAVAJava
javaJavaJAVJavjAv
- 括号和反向引用
前面的例子已经用到了括号,大概有两个用处,第一个是将若干个字符组成一个单元,受量词的作用,第二个是限制多选结构的作用范围。
这里还要说到括号的另外一个作用:反向引用,应用场景如在文本中查找连续的重复单词,因为并不知道重复的单词是什么,也不可能把所有的情况进行穷举,所以需要正则表达式记住前面已经匹配的内容。具体实例如下所示,可以仔细思考下,下例是怎么实现的,其中’\1’表示’()’所记忆的内容,如果表达式中出现多组括号,则分别用’\1’、’\2’、’\3’···表示第一第二第三个括号内的内容。