grep与正则

一、 grep介绍

grep命令主要用于过滤文本,grep家族如下

grep: 在文件中全局查找指定的正则表达式, 并打印所有包含该表达式的行
egrep:扩展的egrep,支持更多的正则表达式元字符
fgrep:固定grep(fixed grep),有时也被称作快速(fast grep),它按字面解释所有的字符

1.1 grep命令格式

grep 命令的输入可以来自标准输入或管道,而不仅仅是文件,例如:

ps aux |grep 'nginx'

1.2 grep选项

-n, --line-number			在过滤出的每一行前面加上它在文件中的相对行号
-o, --only-matching			只显示匹配的内容
-q, --quiet, --silent		静默模式,没有任何输出,得用$?来判断执行成功没有,即有没有过滤到想要的内容
--color						颜色
-i, --ignore-case			忽略大小写
-A, --after-context=NUM		如果匹配成功,则将匹配行及其后n行一起打印出来
-B, --before-context=NUM	如果匹配成功,则将匹配行及其前n行一起打印出来
-C, --context=NUM			如果匹配成功,则将匹配行及其前后n行一起打印出来
-c, --count					如果匹配成功,则将匹配到的行数打印出来
-v, --invert-match			反向查找,只显示不匹配的行
-w							匹配单词
-E							等于egrep,扩展



-l, --files-with-matches	如果匹配成功,则只将文件名打印出来,失败则不打印
							通常-rl一起用,grep -rl 'root' /etc 
-R, -r, --recursive			递归

语法:

grep [选项] PATTERN 文件1 文件2 ...

[root@manager ~]# grep 'root' /etc/passwd
[root@manager ~]# fgrep 'bash' /etc/passwd
找到:			 grep返回的退出状态为0
没找到:			 grep返回的退出状态为1
找不到指定文件:	 grep返回的退出状态为2

1.3 示例

# 1-n
[root@manager ~]# grep -n 'root' /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/root:/sbin/nologin
[root@manager ~]# 

# 2-o
[root@manager ~]# grep -o 'root' /etc/passwd
root
root
root
root
[root@manager ~]# 

# 3-q
[root@manager ~]# grep -q 'root' /etc/passwd 
[root@manager ~]# echo $?
0

# 4--color
[root@manager ~]# alias grep
alias grep='grep --color=auto'
[root@manager ~]# 

# 5-i
[root@manager ~]# echo "BERtwu" |grep -i bertwu 
BERtwu
[root@manager ~]# 

# 6-A\-B\-C
[root@manager ~]# grep -A 2 'root' /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
--
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin


[root@manager ~]# grep -B 2 'root' /etc/passwd
root:x:0:0:root:/root:/bin/bash
--
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin


[root@manager ~]# grep -C 2 'root' /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
--
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
[root@manager ~]# 


# 7-c
[root@manager ~]# grep -c 'root' /etc/passwd
2
[root@manager ~]# 

# 8-v
[root@manager ~]# ps aux | grep nginx |grep -v grep
[root@manager ~]# 
[root@manager ~]# ps aux | grep [n]ginx
[root@manager ~]# 

# 9-w
[root@manager ~]# netstat -an |grep -w 80
tcp6       0      0 :::80                   :::*                    LISTEN    
[root@manager ~]# netstat -an |grep  '\<80\>'
tcp6       0      0 :::80                   :::*                    LISTEN    
[root@manager ~]# netstat -an |grep  '\b80\b'
tcp6       0      0 :::80                   :::*                    LISTEN   
                        
                        
# 10-rl
[root@manager ~]# grep -rl 'root' /etc  # 将/etc目录下所有包含'root'内容的文件都列出来

二、正则表达式

2.1 什么是正则表达式

正则表达式,又称规则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE),是计算机科学的一个概念。正则表达式由元字符组成,通常被用来检索、替换那些符合某个模式(规则)的文本(许多程序设计语言都支持利用正则表达式进行字符串操作)。
在这里插入图片描述

2.2 为何需要正则表达式

再工作中,我们时刻面对着大量的日志,程序,以及命令的输出。迫切的需要过滤我们需要的一部分内
容,甚至是一个字符串。比如: 现在有一个上千行的文件,我们仅需要其中包含“ERROR”的行,怎么办? 此时就需要使用到正则表达式的规则来筛选想要的内容。

2.3 正则表达式注意事项

1.正则表达式应用非常广泛,存在于各种编程语言中。
2.正则表达式和Linux的通配符以及特殊字符是有区别的 。rm -rf * grep *
3.要想学好grep、sed、awk首先就需要对正则表达式有一定的了解。只有了解了规则,才能灵活的运用。

2.4 基本正则元字符集

元字符		  功能									     示例	
^ 			  行首										^love
$ 			  行尾										 love$
^$            表示空行
. 			  除了换行符\n 以外的任意单个字符				 l..e
* 			  前导字符的零个或多个						     ab*love
.* 			  所有字符									 a.*love
[] 			  字符组内的任一字符							 [lL]ove
[^] 		  对字符组内的每个字符取反(不匹配字符组内的每个字符)   [^a-z0-9]ove
^[^] 	      匹配非字符组内的字符开头的行
?             匹配之前的项1次或者0+             匹配之前的项1次或者多次 [0-9]+
*             匹配之前的项0次或者多次 .* 
[a-z] 		  小写字母
[A-Z] 		  大写字母
[a-Z] 	      小写和大写字母
[0-9] 	      数字

\	  		 用来转义元字符,忽略其特殊意义 									  love\.	
\< 		     词首定位符 单词一般以空格或特殊字符做分隔、连续的字符组成  \<love
\> 			 词尾定位符										   love\>
\(..\)		 匹配稍后将要使用的字符的标签	                \(love\)able\1er	
                                                         :1,$ s/\(192.168.11\).66/\1.50/g

x\{
    
    m\}			字符x重复出现m次							     e\{
    
    3\}
x\{
    
    m,\}			字符x重复出现m次以上								e\{
    
    3,\}						
x\{
    
    m,n\}		字符x重复出现m到n次								e\{
    
    3,6\}	



#posix
[[:space:]]     匹配空格
[[:digit:]]     匹配[0-9]
[[:lower:]]     匹配[a-z]
[[:upper:]]     匹配[A-Z]
[[:alpha:]]     匹配[a-Z]

示例

1^ 行首
[root@manager ~]# grep '^root' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@manager ~]# 

# 2、$ 行尾
tom:x:6668:6668::/home/tom:/bin/bash
[root@manager ~]# grep 'bash$' /etc/passwd
root:x:0:0:root:/root:/bin/bash
tom1:x:1000:1000::/home/tom1:/bin/bash
tom2:x:1001:1001::/home/tom2:/bin/bash
tom3:x:1002:1002::/home/tom3:/bin/bash
tom4:x:1003:1003::/home/tom4:/bin/bash
tom5:x:1004:1004::/home/tom5:/bin/bash
jack:x:6667:6667::/home/jack:/bin/bash
tom:x:6668:6668::/home/tom:/bin/bash



# 3. 除了换行符以外的任意单个字符
[root@manager ~]# grep 'r..t' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin


# 4* 前导字符的零个或多个
[root@manager ~]# cat a.txt 
a

ab
abb
abbb
bbbbb
[root@manager ~]# grep 'ab*' a.txt 
a
ab
abb
abbb
[root@manager ~]# 

# 5.* 所有字符=贪婪
[root@manager ~]# cat a.txt 
a123+-*/c11113333c
a1c
a77Ac
a23333c
ac
111
222
333
[root@manager ~]# grep 'a.*c' a.txt 
a123+-*/c11113333c
a1c
a77Ac
a23333c
ac
[root@manager ~]# 

# 5.1 .*?=》非贪婪,默认情况下,grep不支持非贪婪修饰符,但您可以使用grep -P来使用Perl语法来支持.*?
[root@manager ~]# cat a.txt 
<a href="http://www.baidu.com">"我是百度"</a>
<a href="http://www.sina.com.cn">"我是新浪"</a>
[root@manager ~]# 

[root@manager ~]# grep -o 'href=".*"' a.txt  # 贪婪匹配
href="http://www.baidu.com">"我是百度"
href="http://www.sina.com.cn">"我是新浪"

[root@manager ~]# 

[root@manager ~]# grep -oP 'href=".*?"' a.txt  # 非贪婪
href="http://www.baidu.com"
href="http://www.sina.com.cn"
[root@manager ~]# 



# 6[] 字符组内的任一字符
# 7[^] 对字符组内的每个字符取反(不匹配字符组内的每个字符)
[root@manager ~]# cat a.txt 
a1c
a2c
a33c
aAc
aZc
[root@manager ~]# grep 'a[0-9]c' a.txt
a1c
a2c
[root@manager ~]# grep 'a[^0-9]c' a.txt
aAc
aZc
[root@manager ~]# 
[root@manager ~]# grep 'a[0-9][0-9]c' a.txt
a33c
[root@manager ~]# 

# 8^[^] 非字符组内的字符开头的行
[root@manager ~]# cat a.txt 
a1c
a2c
a33c
aAc
aZc
[root@manager ~]# grep '^[^0-9]..$' a.txt
a1c
a2c
aAc
aZc
[root@manager ~]# 

# 9[a-z] 小写字母
# 10[A-Z] 大写字母
# 11[a-Z] 小写和大写字母
# 12[0-9] 数字

# 13、\< 单词头 单词一般以空格或特殊字符做分隔,连续的字符串被当做单词
# 14、\> 单词尾
[root@manager ~]# netstat -an |grep -w 80
tcp6       0      0 :::80                   :::*                    LISTEN    
[root@manager ~]# netstat -an |grep  '\<80\>'
tcp6       0      0 :::80                   :::*                    LISTEN    
[root@manager ~]# netstat -an |grep  '\b80\b'
tcp6       0      0 :::80                   :::*                    LISTEN  

grep匹配换行符和制表符

[root@manager ~]# echo -e "a\nb" |grep $'a\nb'
a
b
[root@manager ~]# 
[root@manager ~]# echo -e "a\tb" |grep $'a\tb'
a	b
[root@manager ~]# 

2.5 扩展正则元字符集

# 扩展正则元字符
+					匹配一个或多个前导字符		   [a-z]+ove	
?					匹配零个或一个前导字符		   lo?ve	
a|b					匹配a或b					love|hate
()					组字符						love(able|rs)  (bertwu)+
(..)(..)\1\2		标签匹配字符				  (love)able\1er
x{
    
    n}			    x出现n次				    e{
    
    3}		
x{
    
    n,}			    x出现n次至无穷次			  e{
    
    3,}
x{
    
    n,m}		        x出现n次至m次			   e{
    
    3,6}

# 若想使用扩展正则
grep加-E 或 egrep 或转义\

sed 加 -r 参数 或转义

awk 直接支持大多数扩展正则,更多支持需要加选项--posix选项
# ======================grep扩展正则示例======================
[root@manager ~]# cat a.txt 
a

ab
abb
abbb
abbbb
abbbbb
bbbbbbb
[root@manager ~]# grep 'ab{2,4}' a.txt  # 默认不支持扩展正则,所以没效果
[root@manager ~]# egrep -o 'ab{2,4}' a.txt
abb
abbb
abbbb
abbbb
[root@manager ~]# grep -o 'ab\{2,4\}' a.txt # 或者转义
abb
abbb
abbbb
abbbb
[root@manager ~]# 

# ======================sed扩展正则示例======================
[root@manager ~]# sed -n '/roo?/p' /etc/passwd  # 默认不支持扩展正则?
[root@manager ~]# sed -n '/roo\?/p' /etc/passwd  # 可以用\转义扩展正则符号?
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin

[root@manager ~]# sed -rn '/roo?/p' /etc/passwd  # 也可以加-r选项
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
[root@manager ~]# 

# ======================awk扩展正则示例======================
[root@manager ~]# cat a.txt 
a

ab
abb
abbb
abbbb
abbbbb
bbbbbbb
[root@manager ~]# awk '/ab{1,3}/{print}' a.txt
ab
abb
abbb
abbbb
abbbbb
[root@manager ~]# awk --posix '/ab{1,3}/{print}' a.txt
ab
abb
abbb
abbbb
abbbbb
[root@manager ~]# 

总结

grep:				使用基本元字符集	^, $, ., *, [], [^], \< \>,\(\),\{
    
    \}
egrep(或grep -E):	使用扩展元字符集	?, +, {
    
     }, |, ( )
# 注:grep也可以使用扩展集中的元字符,仅需要对这些元字符前置一个反斜线

补充:
\w	所有字母与数字,称为字符[a-zA-Z0-9]	   'l[a-zA-Z0-9]*ve'	   		'l\w*ve'
\W	所有字母与数字之外的字符,称为非字符	   'love[^a-zA-Z0-9]+' 	        'love\W+'
\b	词边界								'\blove\b'					  '\<love\>'

2.6 posix定义的字符分类

# 表达式       	  功能                              			示例
[:alnum:]     	字母与数字字符                       		[[:alnum:]]+  
[:alpha:]  		字母字符(包括大小写字母)					  [[:alpha:]]{
    
    4}
[:blank:]     	空格与制表符                         		  [[:blank:]]*
[:digit:]       	数字字母                            	[[:digit:]]?
[:lower:]      	小写字母                            		[[:lower:]]{
    
    5,}
[:upper:]      	大写字母                            		[[:upper:]]+
[:punct:]      	标点符号                            		[[:punct:]]
[:space:]      	包括换行符,回车等在内的所有空白[[:space:]]+


# 详解
[:alnum:] Alphanumeric characters.
匹配范围为 [a-zA-Z0-9]
[:alpha:] Alphabetic characters.
匹配范围为 [a-zA-Z]
[:blank:] Space or tab characters.
匹配范围为 空格和TAB键
[:cntrl:] Control characters.
匹配控制键 例如 ^M 要按 ctrl+v 再按回车 才能输出
[:digit:] Numeric characters.
匹配所有数字 [0-9]
[:graph:] Characters that are both printable and visible. (A space is print-
able, but not visible, while an a is both.)
匹配所有可见字符 但不包含空格和TAB 就是你在文本文档中按键盘上能用眼睛观察到的所有符号
[:lower:] Lower-case alphabetic characters.
小写 [a-z]
[:print:] Printable characters (characters that are not control characters.)
匹配所有可见字符 包括空格和TAB
能打印到纸上的所有符号
[:punct:] Punctuation characters (characters that are not letter, digits, con-
trol characters, or space characters).
特殊输入符号 +-=)(*&^%$#@!~`|\"'{
    
    }[]:;?/>.<,
注意它不包含空格和TAB
这个集合不等于^[a-zA-Z0-9]
[:space:] Space characters (such as space, tab, and formfeed, to name a few).

[:upper:] Upper-case alphabetic characters.
大写 [A-Z]
[:xdigit:] Characters that are hexadecimal digits.
16进制数 [0-f]

# 使用方法:
[root@egon ~]# grep --color '[[:alnum:]]' /etc/passwd

2.7 示例

1.提取服务器网卡地址

[root@manager ~]# ifconfig eth0 | egrep -o "inet ([0-9]{1,3}\.){3}[0-9]{1,3}"
inet 10.0.0.99

[root@manager ~]#ifconfig eth0 | grep -o "inet \([0-9]\{1,3\}\.\)\{1,3\}[0-9]\{1,3\}" | awk 'NR==1{
    
    print $0} #grep扩展正则时,比较麻烦

2.使用 grep 正则表达式方式,排除 selinux日志文件的空行和#号开头的行

[root@manager ~]# grep -v  "^$\|^#" /etc/selinux/config
SELINUX=disabled
SELINUXTYPE=targeted 

或者
[root@manager ~]# egrep -v  "^$|^#" /etc/selinux/config 
SELINUX=disabled
SELINUXTYPE=targeted 
或者
[root@manager ~]# egrep  -v "(^$|^#)" /etc/selinux/config 
SELINUX=disabled
SELINUXTYPE=targeted 

加不加括号都行

3.匹配日志中的http版本

[root@manager ~]# grep  -o "HTTP/\(1\|2\|3\).\(0\|1\)" access.1w_oldxu.log  | sort | uniq
HTTP/1.0
HTTP/1.1
[root@manager ~]# egrep  -o "HTTP/(1|2|3).(0|1)" access.1w_oldxu.log  | sort | uniq
HTTP/1.0
HTTP/1.1

4.匹配无注释的配置文件

[root@manager ~]# grep -v "^#\|^$" /etc/nginx/nginx.conf

5. 匹配用户手机号是否合法

[root@manager ~]# cat grep_phone.sh 
[root@manager ~]# cat grep_phone.sh 
while :
do
	read -p "请输入合法的手机号,按q|Q退出:" action
	if [ ${
    
    action^} == "Q" ];then
		break
	fi

	#if [[ $action =~ ^1(3|5|6|7|8|9)[0-9]{
      
      9}$ ]];then # 方式1
	if [[ $action =~ ^1[356789][0-9]{
    
    9}$ ]];then    # 方式二
		echo "您输入的$action手机号合法"
		break
	fi
	
	echo "您输入的$action手机号不合法,请重新输入"
done



6. 匹配用户邮箱是否合法

需求:使用 grep 正则表达式方式,匹配 qq、163、sina 的 email 地址。
前缀:数字|字母 组成方式 (长度,不可以超过16)
@ 正常出现
qq | sina | foxmail | 163 | gmail 固定的字段;
.com .cn .org 不做控制;

[root@manager ~]# cat grep_mail.sh 
while true
do
 	read -p "请输入合法邮箱 q|Q 退出: " action
	if [ ${
    
    action^} == "Q" ];then
		break
	fi


	if [[ $action =~ ^[0-9a-zA-Z]{
    
    1,16}\@(qq|sina|foxmail|163|gmail)\.(com|cn|org)$ ]];then
		echo "您输入的邮箱 $action 合法"
		break
	fi
	echo "您输入的邮箱 $action 不合法,请重新输入"
done

7.匹配特殊域名

匹配如下域名
[root@manager ~]# cat aa.txt 
xxt-demo.shop.oldxu.com
xxt-demoadmin.shop.oldxu.com
abc.shop.oldxu.com
abcadmin.shop.oldxu.com
123.shop.oldxu.com
abc123.shop.oldxu.com
[root@manager ~]# 

[root@manager ~]# egrep '^([a-z0-9]+-[a-z]+|[a-z0-9]+)\.shop.oldxu.com$' aa.txt 
或者
[root@manager ~]# egrep '^([a-z0-9]{1,}-[a-z]{1,}|[a-z0-9]{1,})\.shop.oldxu.com$' aa.txt 

猜你喜欢

转载自blog.csdn.net/m0_46090675/article/details/120553674
今日推荐