linux学习笔记:grep命令,正则表达式
-
grep, 正则表达式的作用
在生产环境或者实验环境中,我们经常会对linux操作系统下的日志以及配置文件进行文本处理,从中截获、修改我们感兴趣的内容,进行分析和处理。通过grep命令,结合正则表达式,可以灵活地完成各种文本处理,从而达到事半功倍的目的。 -
grep命令的常用选项
完全详细的grep命令的选项以及作用,可以参照man手册,或者google,这里仅总结一些常用的选项:
命令选项 | 解释 |
---|---|
-v | 显示不被pattern匹配到的行 |
-i | 忽略字母的大小写 |
-n | 显示匹配的行号 |
-c | 统计匹配的行数 |
-o | 仅显示匹配到的字符串 |
-q | 静默模式,不输出任何信息 |
-A <num> | 不仅输出匹配的行,同时输出该匹配行后面的num行 |
-B <num> | 不仅输出匹配的行,同时输出该匹配行之前的num行 |
-C <num> | 不仅输出匹配的行,同时输出该行前后各num行 |
-e | 实现多个选项之间的逻辑or关系 |
-w | 匹配整个单词 |
-E | 使用egrep扩展模式进行正则匹配 |
-F | 相当于fgrep(fast grep),并不支持正则表达式 |
$ cat /etc/nsswitch.conf | grep -v "^#" | grep -v "^$" #删空行和注释行 passwd: files sss shadow: files sss group: files sss ...... ......
$ echo "HELLO" | grep -i "hello" #不区分大小写的匹配 HELLO
$ cat /etc/passwd | grep -c bash #统计使用bash用户的数量 3 ...... ...... $ cat /etc/passwd | grep -n bash #匹配使用bash用户的行并添加行号 1:root:x:0:0:root:/root:/bin/bash 23:user1:x:1000:1000::/home/user1:/bin/bash 24:guest:x:1002:1002::/home/guest:/bin/bash ...... ...... $ cat /etc/passwd | grep -o bash #仅仅显示匹配到的字符串本身 bash bash bash ...... ...... $ cat /etc/passwd | grep -q bash; echo $? #静默模式 0 $ cat /etc/passwd | grep -q abcdefg; echo $? #静默模式 1 ...... ...... $ cat grep -A3 -B3 "^\bshutdown\b" /etc/passwd #shutdown前后3行 adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin $ cat grep -C3 "^\bshutdown\b" /etc/passwd #同上 adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin ...... ...... $ grep -e "root" -e "lp" -e "ftp" /etc/passwd #逻辑或 root:x:0:0:root:/root:/bin/bash lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin ...... ...... $ cat 1.txt /bin/bash bash/bin bash /bin/bash/bin binbashbin $ cat 1.txt | grep -w bash #-w选项无法匹配binbashbin中的bash /bin/bash bash/bin bash /bin/bash/bin ...... ......
-
linux,grep,与正则表达式
正则表达式的实现(参见:正则引擎)有很多种,在linux操作系统里面,默认引擎为PCRE(Perl Compatible Regular Expressions),依照维基百科,PCRE库、Perl语言、PHP语言、Python语言,对正则表达式的支持是最好的。linux系统的程序,如grep, sed, awk, vim, less, nginx, varnish等,都支持正则表达式。
针对grep程序,支持基本的正则表达式(BRE)以及扩展的正则表达式(ERE),可以通过grep -E命令或者egrep命令,使用扩展的正则表达式。
更多的正则表达式的内容,可以参见linux下面的man手册: man 7 regex -
正则表达式的元字符
在正则表达式中,具有特殊意义的字符集,称为元字符。常用的元字符如下表所示:
元字符 | 含义 |
---|---|
^ | 行首锚定 |
$ | 行尾锚定 |
. | 匹配任意单个字符 |
[] | []内任意单一字符 |
[^] | 除[]内任意单一字符 |
* | *前面的字符重复0次或者多次 |
\+ | \+前面字符重复1次或者多次 |
\? | ?前面的字符重复0次或者1次 |
\ | 转义符 |
\{n\} | 前面字符重复n次 |
\{n,\} | 前面字符重复n次(包括n次)以上 |
\{m,n\} | 前面的字符重复m次(包括m次)和n次(包括n次)之间 |
[:alnum:] | 字母和数字 |
[:alpha:] | 代表任何英文大小写字母 |
[:lower:] | 小写字母 |
[:upper:] | 大写字母 |
[:blank:] | 水平空白符 |
[:space:] | 垂直空白字符 |
[:cntrl:] | 不可打印的控制字符(退格、删除、警铃……) |
[:digit:] | 十进制数字 |
[:graph:] | 可打印的空白字符 |
[:pnuct:] | 标点符号 |
[:xdigit:] | 十六进制数字 |
示例如下所示:
1. 显示/proc/meminfo文件中以大s或者小s开头的行: $ cat /proc/meminfo | grep -i "^s.*$" $ cat /proc/meminfo | grep "^[sS].*$" 2.显示CentOS7上面所有系统用户的用户名和UID: $ cat /proc/meminfo | grep -v "root" | grep -v "\b[0-9]\{4,\}\b" 3.取出/etc/rc.d/init.d/functions的基名 echo "/etc/rc.d/init.d/functions" | egrep -o "/[[:alpha:]]+$" | \ egrep -o "[[:alpha:]]+" 4.使用egrep取出上面路径的目录名 #贪婪匹配 echo "/etc/rc.d/init.d/functions" | egrep -o "/.*/" 5.找出/etc/rc.d/init.d/functions文件中行首为某单词(包括下划线)后面跟一个小括号的行 $ cat /etc/rc.d/init.d/functions | egrep "^[_[:alpha:]]+\(\)"
-
正则表达式的分组
将一个或者多个字符捆绑在一起,当做一个整体进行处理,例如:\(root\)\+
分组括号中的匹配模式匹配到的内容会被正则引擎记录于内部变量当中,这些变量的分组的命名方式为\1, \2, \3,……
当然,我们也可以自己定义分组名称。利用(?<Word>\w+),这样就会将\w+匹配到的内容赋值给分组Word。可以通过\k<Word>引用这个分组1。
分组的语法格式如下表所示:
表达式 | 解释 |
---|---|
(exp) | 匹配exp, 捕获文本到自动命名的组里面: \1, \2, … |
(?<name>exp) | 匹配exp,捕获文本到名称为name的组里面 |
(?:exp) | 匹配exp,不捕获匹配的文本 |
(?=exp) | 匹配exp前面的位置,但是并不包括exp本身 |
(?<=exp) | 匹配exp后面的位置,但是并不包括exp本身 |
(?!exp) | 匹配后面不是exp的位置,不包括那个不是exp的模式 |
(?<!exp) | 匹配前面不是exp的位置,不包括那个不是exp的模式 |
其中的(?=exp)被称为零宽先行断言,其中的(?<=exp)被成为零宽后行断言。
使用案例如下所示:
1. 找出/etc/passwd下面用户名同shell名的行 $ cat /etc/passwd | grep -P "^\b(\w+):\b.*\1$" ...... ...... 2.匹配开头是/bin/的内容,但是并不包括/bin/本身 [root@centos7-front1 ~]# cat -n 1.txt 1 /bin/bash 2 /bin/bash/bin/ 3 <bash> 4 <bash [root@centos7-front1 ~]# cat 1.txt | grep -noP "(?<=/bin).*" 1:/bash 2:/bash/bin/ ...... ...... 3.匹配结尾为/bin/的内容,但是并不包括/bin/本身 [root@centos7-front1 ~]# cat -n 1.txt 1 /bin/bash 2 /bin/bash/bin/ 3 <bash> 4 <bash [root@centos7-front1 ~]# cat 1.txt | grep -noP "^.*(?=/bin/$)" 2:/bin/bash ...... ...... 3.匹配由两个尖括号包裹的内容,但是并不包括两个尖括号本身 [root@centos7-front1 ~]# cat -n 1.txt 1 /bin/bash 2 /bin/bash/bin/ 3 <bash> 4 <bash [root@centos7-front1 ~]# cat 1.txt | grep -noP "(?<=<).*(?=>)" 3:bash ...... ...... 4.匹配简单html标签 $ echo "<font color=#ff0000>color font</font>" \ | grep -oP "(?<=>).*(?=</font>)" color font ...... ...... 5.匹配出/etc/passwd文件中用户id和数组id相同的用户 $ grep -P ".*\b:(?<UID>\w+):\b\k<UID>.*$" /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin dbus:x:81:81:System message bus:/:/sbin/nologin abrt:x:173:173::/etc/abrt:/sbin/nologin tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin postfix:x:89:89::/var/spool/postfix:/sbin/nologin sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin user1:x:1000:1000::/home/user1:/bin/bash guest:x:1002:1002::/home/guest:/bin/bash nscd:x:28:28:NSCD Daemon:/:/sbin/nologin apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
-
贪婪模式与懒惰模式
当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。以这个表达式为例:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配
有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号?。这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。
懒惰限定符如下表所示:
限定符 | 说明 |
---|---|
*? | 重复任意次,但是尽可能少地重复 |
+? | 重复1次或者更多次,但是尽可能少地重复 |
?? | 重复0次或者1次,但是尽可能少地重复 |
{n,m}? | 重复n到m次,但是尽可能少地重复 |
{n,}? | 重复n次,但是尽可能少地重复 |
使用示例如下所示:
[root@centos7-front1 ~]# echo "aababab" | grep -oP "a.*b" aababab [root@centos7-front1 ~]# echo "aababab" | grep -oP "a.*?b" aab ab ab [root@centos7-front1 ~]# echo "aababab" | grep -oP "a.+?b" aab abab [root@centos7-front1 ~]# echo "aababab" | grep -oP "a.??b" aab ab ab [root@centos7-front1 ~]# echo "aababab" | grep -oP "a.{0,1}?b" aab ab ab [root@centos7-front1 ~]# echo "aababab" | grep -oP "a.{1,}?b" aab abab
注释:
- 使用分组的时候,最好使用grep -P命令,使用Perl正则扩展。 ↩
原创文章,作者:jiangche00,如若转载,请注明出处:http://www.178linux.com/72707
评论列表(1条)
详细的介绍了grep 以及正则表达式,内容写的很不错,版本也非常好,赞!