正则表达式RE以及grep、awk和sed工具的用法详解

1.什么是正则表达式

通俗的来说,正则表达式就是处理字串的方法,他是以行为单位来进行字串的处理行为, 正则表达式通过一些特殊符号的辅助,可以让使用者轻易的达到“搜寻/删除/取代”某特定字串的处理程序!正则表达式基本上是一种“表达式”, 只要工具程序支持这种表达式,那么该工具程序就可以用来作为正则表达式的字串处理之用。 例如 vi, grep, awk ,sed 等等工具,因为她们有支持正则表达式, 所以,这些工具就可以使用正则表达式的特殊字符来进行字串的处理。但例如 cp, ls 等指令并未支持正则表达式, 所以就只能使用 Bash 自己本身的通配符而已。

2.特殊符号以及RE字符

1.特殊符号
特殊符号 代表的含义
[:alnum:] 代表所有的大小写英文字符和数字,即0-9 A - Z a-z
[:alpha:] 代表任意英文大小写字符,即A-Z a-z
[:lower:] 代表小写英文字符,即a-z
[:upper:] 代表大写英文字符 ,即A-Z
[:digit:] 代表数字,即0-9
[:blank:] 代表 空格键或者Tab键
[:cntrl:] 代表键盘上所有的控制按键,如:CR、LF、Tab、Del等等
[:graph:] 代表除了空格键与Tab键之外的其它键
[:print:] 代表的是标点符号,如:’ " ! ? ; # $ 等
[:space:] 代表任何能产生空白字符的按键,如:空格键,Tab,CR等等
[:xdigit:] 代表16进位的数字类型,包括:0-9,A-F,a-f的数字与字符

注意:前五条是常用的,其它一般不怎么用或者能用其它方式代替

2.特殊符号的示例

我们去网上找一些数据来做实例

Hello! / Hi!
Good-bye, "Mike".
See you tomorrow.
It’s time for class.
Open your books and turn to page 20.
Could you say it again? 
Where’s the company? 
Which is the right size? 
Do you know where I’ve put my glasses? 
Is this your pen? I found it under the desk. 
Which is your bag? 
The one on your right. 
Are these books all yours? 
She must be a model, isn’t she? 
I really don’t known.
#I have no idea about it.
What’s your family name?
Rose, let me introduce my friend to you.
Nice to meet you, too.
toooooot 
What day is it today?
It’s January the 15th, 1999.
It’s the year of 1999.
However, this dress is about $ 3183 dollars.
我们将数据写入一个文件里面
[root@localhost tmp]# vim test.text

开始匹配

[root@localhost tmp]# grep "[:alnum:]" test.text         #我们不能直接使用这些特殊符号
grep: 字符类的语法是 [[:space:]],而非 [:space:]
[root@localhost tmp]# grep "[[:alnum:]]" test.text        #我们需要用[]将其括起来

在这里插入图片描述

3.RE字符及用法
RE字符 含义与用法示例
^ 含义:待匹配的在行首
[root@localhost tmp]# grep -n '^#' test.text      #匹配到以#开头的行,并打印出行号
-n 参数表示显示行号

在这里插入图片描述

RE字符 含义与用法示例
$ 含义:待匹配的在行尾
[root@localhost tmp]# grep -n '!$' test.text      #匹配到以#开头的行,并打印出行号

在这里插入图片描述

RE字符 含义与用法示例
. 含义:一个任意字符
[root@localhost tmp]# grep -n 'e.e' test.text      
#匹配到的字符串可以是(ere)(eve),就是两个e中间一定有且仅有一个其它字符,空字符也算。
#但不能是(ee) 如:See you tomorrow.  See虽然有两个e,但是不符合就没有出现

在这里插入图片描述

RE字符 含义与用法示例
\ 含义:转义字符,将特殊符号的特殊意义去掉
[root@localhost tmp]# grep -n '\$' test.text     
#    $   本来是匹配结尾的但是这里转义就能匹配到

在这里插入图片描述

RE字符 含义与用法示例
* 含义:将前面的一个字符重复零次到无穷次
[root@localhost tmp]# grep -n 'to*' test.text   
#  匹配到单个t(零次o) 匹配到too (多次o)  

在这里插入图片描述

RE字符 含义与用法示例
[] 含义:[]表示匹配到里面其中一个字符
[root@localhost tmp]# grep -n 'o[nmt]' test.text  
# [nmt]代表n或m或t 所以会匹配到(on)(om)(ot)  

在这里插入图片描述

[root@localhost tmp]# grep -n '[0-9]' test.text  
#[0-9]就相当于[0123456789]   

在这里插入图片描述

RE字符 含义与用法示例
[^] 含义:表示匹配到除了里面之外的字符
[root@localhost tmp]# grep -n 'on[^e]' test.text 
#[^e] 表示除了e之外其它字符都可以即匹配不到one
#空字符也算

在这里插入图片描述

RE字符 含义与用法示例
{n,m} 含义:前一个字符重复n到m次
[root@localhost tmp]# grep -n 'to\{1,3\}' test.text 
#重复o 一到三次
#要跟* 区分 *表示重复零次到无穷多次

在这里插入图片描述
在这里插入图片描述

3.grep

1.grep一些能跟正则搭配的参数
-A   n  	把匹配成功行之后的n行也同时列出。 A 就是 after 的首字母就是之后的意思
-B   n  	把匹配成功行之前的n行也同时列出。B 就是 before 的首字母就是之前的意思
-C  n  	把匹配成功行的前后n行也同时列出。
-o   		只显示匹配到的字符
-c   		统计数量    (一般是跟其它参数一起用)
-n   		显示行号     (前面说过了)
-l			只要文件名   
2.gerp的扩展正则

用扩展正则必须用egrep 或者grep -E

RE字符 含义与用法示例
+ 含义:前一个字符重复一次或一次以上
含义:前一个字符重复零次或一次
| 含义:表示或者
() 含义:群组字串
()+ 含义:前一个群组字串重复一次或一次以上
这里面+  和 ?  我就不多说了,注意要比较和* 的区别
而 |  的用法也特别简单比如:
 [root@localhost tmp]# echo "tooooabsdsadooo"  | grep -E 'too|ab'     #表示匹配too或者ab
tooooabsdsadooo             #too  和 ab  将被标红
[root@localhost tmp]# echo "goodaaaglad"  | grep -E 'g(oo|la)d'          #表示匹配到good或者glad
goodaaaglad                  #good和glad将被标红
[root@localhost tmp]# echo "goodgabcabcabcglad"  | grep -E 'g(abc)+g'  #是匹配到gabcabcabcg
goodgabcabcabcglad        #找的是以g开头g结尾,中间是一个以上的abc

写出匹配日期格式 YYYY-MM-DD 的正则表达式(要仔细琢磨)

[root@localhost tmp ~]# echo "2019-12-30" |grep -E '[1-9][0-9]{3}-((0[1-9])|(1[0-2]))-((0[1-9])|([12][0-9])|(3[01]))'
2019-12-30
[root@localhost tmp ~]# echo "1919-12-30" |grep -E '[1-9][0-9]{3}-((0[1-9])|(1[0-2]))-((0[1-9])|([12][0-9])|(3[01]))'
1919-12-30

正则高级部分: 贪婪|非贪婪(了解就好)
贪婪 就是尽可能的多匹配
非贪婪 就是尽可能的少匹配,只需要在一些表示量词(就是次数)的后面加上 ?, 比如: .*? +?
grep 或者 egrep 默认都是贪婪模式,不支持非贪婪模式。
要想实现非贪婪需要使用 -P 参数,这会使用 Perl 语言环境的正则在这里插入图片描述

4.awk

1.awk简介

awk的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到屏幕上,如果没有指定模式,则所有被操作所指定的行都被处理。

2.awk用法

awk [options] ‘commands’ filenames
awk [options] -f awk-script-file filenames -f 表示从脚本文件中读取awk命令
options:
-F 对于每次处理的内容,可以指定一个子定义的分隔符,默认的分隔符是空白字符(空格或 tab 键 )
command:

BEGIN{}            	处理匹配到内容之前的动作
{}             				处理匹配到内容之中的动作
END{}            		处理匹配到内容之中的动作
3.工作原理

(1)awk是一行一行处理的,每次处理时,使用一行作为输入,并将这一行赋给内部变量$0,以换行符结束
(2)每行会被分隔符分成多个字段,每个字段存储在已编号的变量中,从$1开始,最多达100个字段
(3)初始时,FS赋为空白字符,所以默认为以空格为分隔符
(4)awk打印字段时,将以内置的方法使用 print 函数打印,awk 在打印出的字段间加上空格。这个空格是内部的一个变量 OFS 输出字段的分隔符, 逗号 , 会和 OFS 进行映射,通过 OFS 可以控制这个输出分隔符的值。
(5)awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕

4.与字段有关的内部变量
$0 : awk变量 $0 保存当前正在处理的行内容
NR : 当前正在处理的行是 awk 总共处理的行号。
FNR: 当前正在处理的行在其文件中的行号。
NF :每行被处理时的总字段数
$NF: 当前处理行的分隔后的最后一个字段的值
FS : 字段分隔符,默认空格
OFS : 输出字段分隔符,默认是一个 空格
ORS 输出记录分隔符, 默认是换行符.
[root@localhost tmp ~]# awk 'BEGIN{FS=":"} {print $NF}' /etc/passwd     #以:(冒号)为分隔符,输出每一行的最后一个字段的值
[root@localhost tmp]# awk 'BEGIN{FS=":"; OFS="+++"} /^root/{print $1,$2,$3,$4}' /etc/passwd
root+++x+++0+++0                  #输出时以+++隔开
[root@localhost tmp]# awk 'BEGIN{ORS="  "} {print $0}' /etc/passwd #将文件的所有行合并为一行
5.awk模式和动作

awk语句是由模式和动作组成的
模式可以是正则表达式,比较表达式等,而动作一般都是打印print
1.正则表达式:

awk '/正则表达式/'     filename      整行匹配   /正则表达式/  或 !/正则表达式/ 或 $0 ~ /正则表达式/
awk '字段 ~ /正则表达式/'     filename      某一字段匹配 字段 ~ /正则表达式/ 或 字段 !~ /正则表达式/
[root@localhost tmp]# awk -F: '/alice/' /etc/passwd      #只要有anlice就行
[root@localhost tmp]# awk -F: '$NF !~ /alice/' /etc/passwd      #最后一个字段不是anlice

2.比较表达式

== 等于 
!= 不等于                      
< 小于 
> 大于
<= 小于 
>= 大于等于

== 等于 != 不等于 两边可以是数字也可以是字符串

[root@localhost tmp]# awk -F: '$NF == "alice" ' /etc/passwd      #最后一个字段是anlice (别忘了字符串要引起来)
[root@localhost tmp]# awk -F: '$3== 0' /etc/passwd      #第三个字段是0
[root@localhost tmp]# awk -F: '$3 > 0 ' /etc/passwd      #第三个字段大于0

3.条件表达式:if if else
4.逻辑表达式:
&& 与 同时满足
|| 或 满足其中一个
! 非 取反
5.范围模式
起始表达式, 终止表达式

[root@localhost tmp]# awk -F: '/^bin/,/adm/ {print $0 }' /etc/passwd
#从开头是 bin 的行开始匹配成功一直到含有 adm 的行结束匹配(中间的行也都打印出来)

6.外部变量的引用
一般是用awk -v 参数

[root@localhost tmp]# test=hello
[root@localhost tmp]# echo "hello world" | awk -v var=$test '$1 == var {print $1}'
hello

5.sed

sed的工作模式跟awk的一样,都是一行一行的进行处理
sed也支持正则表达式,也支持扩展正则,但是要用-r参数来使用扩展正则。所以在实际使用中一般都加上-r参数,即使你使用的不是扩展正则也不会报错。
sed 默认会输出文件的每一行,无论这行内容是否能匹配上匹配模式,假如被匹配到的则会再输出一次。屏蔽默认输出使用 -n 参数
-i 参数是改变文件里面的内容,不加这个参数,只是输出的时候改变,但是实际上文件里面没有变化

1.实际中用的最多的----搜索替换
# 搜索每一行,找到有 root 的,把第一个替换为yjssjm
sed  -rn  's/root/yjssjm/'   filename
# 搜索每一行,找到所有的 root 字符,进行全局替换为 yjssjm
sed  -rn  's/root/yjssjm/g'   filename     
# i  是同时忽略大小写
sed  -rn  's/root/yjssjm/gi'    filename #也就是可以将Root ROot 等替换成yjssjm
# 找到含有 root 的进行删除
sed  -rn  '/root/d'   filename
# 可以使用不同的 字符 作为界定符号,注意进行转义
sed  -rn  '\#root#d'  filename
# 第 1 行到第 3 行都删除
sed  -r  '1,3  d'    filename
2.sed常用命令

1.替换命令:s

# 将所有的两位数字后面加.5
[root@localhost tmp]# echo "77      1"|sed -r 's/[0-9][0-9]/&.5/'
77.5      1
#/()/\1/  注意格式
[root@localhost tmp]# echo "nowrite" | sed -r 's/(no)write/\1写/'
no写

2.追加命令:a (在匹配到的这一行后面追加)

[root@localhost tmp]# echo "aaaaaaa" | sed -r 'a\111111111'
aaaaaaa
111111111

3.插入命令:i (在匹配到的这一行前面插入)

[root@localhost tmp]# echo "aaaaaaa" | sed -r 'i\111111111'
111111111
aaaaaaa

4.修改命令:c

[root@localhost tmp]# echo "aaaaaaa" | sed -r 'c\111111111'
111111111
3.多重编辑选项:-e
sed -re '1,3 d' -re 's/root/yjssjm/' filename
等同于
sed -r '1,3 d; s/root/yjssjm/' filename
或者多行命令
sed -r '1,3 d' filename
sed -r 's/root/yjssjm/'dfilename
4.常见的操作

在文件中使用 :set list 就能看出来一些不显示的特殊符号
比如:$在开头表示空行,$在末尾表示回车

删除配置文件中被注释的行
sed -ri '/^#/d' filename
删除配置文件中空行
sed -ri '/^$/d' filename
删除开头的一个或者多个空格或者Tab键
sed -ri '/^[ \t]*#/d' filename
给文件3到7行添加注释
sed -r '3,7s/^/#/' filename
发布了31 篇原创文章 · 获赞 91 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/baidu_38803985/article/details/105023004