grep这个应用程序最早由肯·汤普逊写成。grep原先是ed下的一个应用程序,名称来自于g/re/p(globally search a regular expression and print,以正规表示法进行全域查找以及打印)。在ed下,输入g/re/p这个命令后,会将所有符合先定义样式的字符串,以行为单位打印出来。在1973年,Unix第四版中,grep首次出现在man页面中。
grep是一个最初用于Unix操作系统的命令行工具。在给出文件列表或标准输入后,grep会对匹配一个或多个正则表达式的文本进行搜索,并只输出匹配(或者不匹配)的行或文本。
egrep和fgrep命令只跟grep有很小不同。egrep是grep的扩展,支持更多的re元字符, fgrep就是fixed grep或fast grep,它们把所有的字母都看作单词,也就是说,正则表达式中的元字符表示回其自身的字面意义,不再特殊。linux使用GNU版本的grep。它功能 更强,可以通过-G、-E、-F命令行选项来使用egrep和fgrep的功能。
正则表达式(Regular Expression, REGEX)
就是用一个“字符串”来描述一个特征,然后去验证另一个“字符串”是否符合这个特征。比如 表达式“ab+” 描述的特征是“一个 'a' 和 任意个 'b' ”,那么 'ab', 'abb', 'abbbbbbbbbb' 都符合这个特征。
grep正则表达式元字符集
^ | 锚定行的开始 如:'^grep'匹配所有以grep开头的行。 |
$ | 锚定行的结束 如:'grep$'匹配所有以grep结尾的行。 |
. | 匹配一个非换行符的字符 如:'gr.p'匹配gr后接一个任意字符,然后是p。 |
* | 匹配零个或多个先前字符 如:'*grep'匹配所有一个或多个空格后紧跟grep的行。 .*一起用代表任意字符。 |
[] | 匹配一个指定范围内的字符,如'[Gg]rep'匹配Grep和grep。 |
[^] | 匹配一个不在指定范围内的字符,如:'[^A-FH-Z]rep'匹配不包含A-R和T-Z的一个字母开头,紧跟rep的行。 |
\(..\) | 标记匹配字符,如'\(love\)',love被标记为1。 |
\< | 锚定单词的开始,如:'\<grep'匹配包含以grep开头的单词的行。 |
\> | 锚定单词的结束,如'grep\>'匹配包含以grep结尾的单词的行。 |
x\{m\} | 重复字符x,m次,如:'0\{5\}'匹配包含5个o的行。 |
x\{m,\} | 重复字符x,至少m次,如:'o\{5,\}'匹配至少有5个o的行。 |
x\{m,n\} | 重复字符x,至少m次,不多于n次,如:'o\{5,10\}'匹配5--10个o的行。 |
\w | 匹配文字和数字字符,也就是[A-Za-z0-9],如:'G\w*p'匹配以G后跟零个或多个文字或数字字符,然后是p。 |
\W | \w的反置形式,匹配一个或多个非单词字符,如点号句号等。 |
\b | 单词锁定符,如: '\bgrep\b'只匹配grep。 |
用于egrep和 grep -E的元字符扩展集
+ | 匹配一个或多个先前的字符。如:'[a-z]+able',匹配一个或多个小写字母后跟able的串,如loveable,enable,disable等。 |
? | 匹配零个或多个先前的字符。如:'gr?p'匹配gr后跟一个或没有字符,然后是p的行。 |
a|b|c | 匹配a或b或c。如:grep|sed匹配grep或sed |
() | 分组符号,如:love(able|rs)ov+匹配loveable或lovers,匹配一个或多个ov。 |
x{m},x{m,},x{m,n} | 作用同x\{m\},x\{m,\},x\{m,n\} |
POSIX字符类
为了在不同国家的字符编码中保持一至,POSIX(The Portable Operating System Interface)增加了特殊的字符类,如[:alnum:]是A-Za-z0-9的另一个写法。要把它们放到[]号内才能成为正则表达式,如[A- Za-z0-9]或[[:alnum:]]。在linux下的grep除fgrep外,都支持POSIX的字符类。
[:alnum:] | 文字数字字符 |
[:alpha:] | 文字字符 |
[:digit:] | 数字字符 |
[:graph:] | 非空字符(非空格、控制字符) |
[:lower:] | 小写字符 |
[:cntrl:] | 控制字符 |
[:print:] | 非空字符(包括空格) |
[:punct:] | 标点符号 |
[:space:] | 所有空白字符(新行,空格,制表符) |
[:upper:] | 大写字符 |
[:xdigit:] | 十六进制数字(0-9,a-f,A-F) |
建立测试样本 /tmp/greptest.txt
abcdefghijklmnopqrstuvwxyz1234567890
ABCDEFGHIGKLMNOPQRSTUVWXYZ
~!@#$%^&*()_+-=[]\{}|;':",./<>?
aabbccddeeffgg
aaabbbcccdddfffggg
grep的命令选项
常用选项:
--color=auto:对匹配到的文本着色后高亮显示
-i:--ignore-case忽略字符大小写
[root@localhost tmp]# grep -i a greptest.txt
abcdefghijklmnopqrstuvwxyz1234567890
ABCDEFGHIGKLMNOPQRSTUVWXYZ
aabbccddeeffgg
aaabbbcccdddfffggg
aaaabbbbccccdddd
-o:--only-matching仅显示匹配 到的文本自身
[root@localhost tmp]# grep -o a greptest.txt
a
a
a
a
a
a
a
a
a
a
-v, --invert-match:反向匹配
[root@localhost tmp]# grep -v a greptest.txt
ABCDEFGHIGKLMNOPQRSTUVWXYZ
~!@#$%^&*()_+-=[]\{}|;':",./<>?
-E:--extended-regexp支持扩展的正则表达式
-q, --quiet, --silient:静默模式,不输出任何信息 #使用echo $? 查询是否正确执行,正确为0
-?
同时显示匹配行上下的?行,如:grep -2 pattern filename同时显示匹配行的上下2行。
[root@localhost tmp]# grep -1 abc greptest.txt
abcdefghijklmnopqrstuvwxyz1234567890
ABCDEFGHIGKLMNOPQRSTUVWXYZ
[root@localhost tmp]# grep -2 ABC greptest.txt
abcdefghijklmnopqrstuvwxyz1234567890
ABCDEFGHIGKLMNOPQRSTUVWXYZ
~!@#$%^&*()_+-=[]\{}|;':",./<>?
aabbccddeeffgg
-b,--byte-offset
打印匹配行前面打印该行所在的块号码。
[root@localhost tmp]# grep -b aa greptest.txt
96:aabbccddeeffgg
111:aaabbbcccdddfffggg
130:aaaabbbbccccdddd
-c,--count
只打印匹配的行数,不显示匹配的内容。
[root@localhost tmp]# grep -c aa greptest.txt
3
-f File,--file=File
从文件中提取模板。空文件中包含0个模板,所以什么都不匹配。
-h,--no-filename
当搜索多个文件时,不显示匹配文件名前缀。
-l,--files-with-matches
打印匹配模板的文件清单。
-L,--files-without-match
打印不匹配模板的文件清单。
-n,--line-number
在匹配的行前面打印行号。
-s,--silent
不显示关于不存在或者无法读取文件的错误信息。
-w,--word-regexp
如果被\<和\>引用,就把表达式做为一个单词搜索。
-V,--version
显示软件版本信息。
egrep:
支持使用扩展正则表达式的grep命令,相当于grep -E;
分组及引用:
(pattern):分组,括号中的模式匹配到的字符会被记录于正则表达式引擎内部的变量中;
后向引用:\1, \2, ...
或者:
a|b:a或者b
C|cat:表示C或cat
(C|c)at:表示Cat或cat
grep正则表达式举例
# ls -l /etc| grep '^d'
通过管道过滤ls -l输出的内容,只显示以d开头的行(目录文件)
建立/tmp/grepedu.txt
xxxabc
yabc
abcxy
abcy
xxxyabc
abcxy
grep "x\+y" #匹配1次以上的x并以y结尾
abcxy
xxxyabc
abcxy
grep "x\?y" #匹配0次以上的x并以y结尾
yabc
abcxy
abcy
xxxyabc
abcxy
grep "x\{2\}y" #匹配出现2次x(2=n,n>=0)并以y结尾
xxxyabc
\{m,n\}:其前面的字符出现m次,m为非负整数;[m,n]
\{0,n\}:至多n次
\{m,\}:至少m次
显示/etc/passwd文件中不以nologin结尾的行
[root@localhost tmp]# grep -v "nologin$" /etc/passwd
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mageedu:x:1000:1000:mageedu:/home/mageedu:/bin/bash
gentoo:x:5000:5000::/home/gentoo:/bin/bash
fedora:x:5001:5003:Fedora Core:/home/fedora:/bin/tcsh
找出/etc/passwd文件中的三位或四位数
[root@localhost tmp]# grep "\<[0-9]\{3,4\}\>" /etc/passwd
games:x:12:100:games:/usr/games:/sbin/nologin
avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin
systemd-network:x:998:996:systemd Network Management:/:/sbin/nologin
polkitd:x:997:995:User for polkitd:/:/sbin/nologin
mageedu:x:1000:1000:mageedu:/home/mageedu:/bin/bash
gentoo:x:5000:5000::/home/gentoo:/bin/bash
fedora:x:5001:5003:Fedora Core:/home/fedora:/bin/tcsh
#fedora:x:5001:5003abc:Fedora Core:/home/fedora:/bin/tcsh #如果不使用词尾锚定(\>),就会出现数字后带字符的情况。
找出/etc/grub2.cfg文件中,以至少一个空白字符开头,后面又跟了非空白字符的行
grep "^[[:space:]]\+[^[:space:]]" /etc/grub2.cfg
找出"netstat -tan”命令的结果中,以‘LISTEN’后跟0或多个空白字符结尾的行
[root@localhost yum.repos.d]# netstat -tan | grep "LISTEN[[:space:]]*$"
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN
tcp6 0 0 :::22 :::* LISTEN
tcp6 0 0 ::1:25 :::* LISTEN
找出"fdisk -l“命令的结果中,包含以/dev/后跟sd或hd及一个小字母的行
[root@localhost etc]# fdisk -l | grep "/dev/[sh]d[a-z]\>"
Disk /dev/sda: 128.8 GB, 128849018880 bytes, 251658240 sectors
找出”ldd /usr/bin/cat“命令的结果中的文件路径
[root@localhost ~]# ldd /usr/bin/cat|grep "[^[:space:]]"
linux-vdso.so.1 => (0x00007ffc46544000)
libc.so.6 => /lib64/libc.so.6 (0x00007f74a672c000)
/lib64/ld-linux-x86-64.so.2 (0x00007f74a6af3000)
[root@localhost ~]# ldd /usr/bin/cat|grep "/"
libc.so.6 => /lib64/libc.so.6 (0x00007f7b2e1cd000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7b2e594000)
[root@localhost ~]# ldd /usr/bin/cat|grep "/[^[:space:]]"
libc.so.6 => /lib64/libc.so.6 (0x00007f5c6f6b5000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5c6fa7c000)
[root@localhost ~]# ldd /usr/bin/cat|grep "/[^[:space:]]\+"
libc.so.6 => /lib64/libc.so.6 (0x00007fb67bdc8000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb67c18f000)
[root@localhost etc]# ldd /usr/bin/cat | grep -o "/[^[:space:]]\+"
/lib64/libc.so.6
/lib64/ld-linux-x86-64.so.2
找出/proc/meminfo文件中,所有以大写或小写a开头的行;至少用三种方式实现;
egrep "^(a|A)" /tmp/meminfo
grep "^[aA]" /tmp/meminfo
grep -i "^a" /tmp/meminfo
显示当前系统上root,fedora用户的相关信息;
[root@localhost ~]# egrep "^(root|fedora)\>" /etc/passwd
root:x:0:0:root:/root:/bin/bash
fedora:x:5001:5003:Fedora Core:/home/fedora:/bin/tcsh
echo输出一个绝对路径,使用egrep取出其基名;
[root@localhost ~]# echo /tmp/test | egrep -o "[^/]+/?$"
test
找出ip addr list命令结果中的1-255之间的整数;
~]# ip a | egrep "\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>"
转载于:https://blog.51cto.com/9733489/1748749