正则表达式
- 基础正则
- 拓展正则
正则历史
正则表达式,简写:re,全拼:(regular expression)
在某些地区,管它叫做,正规表达式、规则表达式
正则表达式的"祖先"可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和
Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。
1956 年, 一位叫 Stephen Kleene 的数学家在 McCulloch 和 Pitts 早期工作的基础上,发表了一篇标题
为"神经网事件的表示法"的论文,引入了正则表达式的概念。正则表达式就是用来描述他称为"正则集的
代数"的表达式,因此采用"正则表达式"这个术语。
随后,发现可以将这一工作应用于使用 Ken Thompson 的计算搜索算法的一些早期研究,Ken
Thompson 是 Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的 qed 编辑器。
如他们所说,剩下的就是众所周知的历史了。从那时起直至现在正则表达式都是基于文本的编辑器和搜
索工具中的一个重要部分。
为什么使用正则
主要目的:
-
1.方便处理文本和字符串内容
-
2.处理有规律的内容(手机号,身份证)
-
3.正则一般给高级
开发语言
使用
例如:Python,Go,C++,JAVA等(高级开发语言)
awk 和 sed 也是一门语言
搜索和替换操作
但是一般的命令,搜索和替换缺乏灵活性,基本写死。
所以我们可以通过正则表达式,灵活的动态匹配文本。
例如:
-
1.可以测试输入字符串
- 以查看字符串内是否出现电话号码模式或信用卡号码模式。这称为数据验证。
-
2.替换文本。
- 可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它。
- 回车 和 换行
- \r
- \n
-
3.基于模式匹配从字符串中提取子字符串。
-
4.查找文档内或输入域内特定的文本。
正则和通配符的混淆
# 通配符
* 匹配所有
# 正则
* 代表前面的字符出现0次或多次
在linux中使用正则
- 修饰符
- 元字符
# 基础正则
bre (basic regulear expression)
^ 以什么什么开头
$ 以什么什么结尾
. 任意字符
* 前面的字符出现零次或多次
.* 匹配所有字符
[] 主要是一些范围 [0-9] [a-z]
[^] 这是取反 [^0-9]找不是以数字开头的
^[0-9]找以数字开头的
#拓展正则
ere
+ 前面的一个字符或多个字符出现一次或多次
awk -F '[:,]+' '{print $2}'
yys sasadasdasdasd 123:abc : 789
[root@web02 web02]# cat 3.txt | awk -F '[: ]+' '{print $1}'
yys
[root@web02 web02]# cat 3.txt | awk -F '[: ]+' '{print $5}'
789
| 或者
() 被括号起来的东西视为一个整体
sed 里面做后项引用 (.*)
{} 中间一个非负整数,表示大括号前面的内容出现指定次数
[1-9].*
[1-9]+
[1-9]{1,3} 最少出现一次 最多出现三次
? 前面的内容出现零次或一次
# 匹配id
[1-90]{1,3}\.
# {}例子
[root@web02 ~]# grep -E 'z{3}'
z 没有匹配到
zz 没有匹配到
zzz 匹配到了
zzz 过滤结果
? 前面的内容出现0次或一次
正则表达式使用误区
通配符有哪些
# 通配符
* 代表所有内容
{} 只要是生成序列
[root@web02 web02]# echo {1..10}
1 2 3 4 5 6 7 8 9 10
[root@web02 web02]# echo {01..10}
01 02 03 04 05 06 07 08 09 10
[root@web02 web02]# echo {1..10..2}
1 3 5 7 9
[root@web02 web02]# echo {a..z..2}
a c e g i k m o q s u w y
cp /usr/lib/systemd/system/nginx.service{.bak} # 展开得下方路径
cp /usr/lib/systemd/system/{nginx.service,nginx.service.bak}
? 匹配任意一个字符
[root@web02 web02]# ls -l ./s?udent.txt
-rw-r--r-- 1 root root 0 Jul 6 12:32 ./student.txt
[root@web02 web02]# ls -l ./s??dent.txt
-rw-r--r-- 1 root root 0 Jul 6 12:32 ./student.txt
[root@web02 web02]# ls -l ./???????.txt
-rw-r--r-- 1 root root 0 Jul 6 12:32 ./student.txt
[root@web02 web02]# touch hhh.txt
[root@web02 web02]# ls -l ./???.txt
-rw-r--r-- 1 root root 0 Jul 6 12:33 ./hhh.tx
# 以下两个与正则表达式中无异
[] 范围
[^] 以不是这个范围的
[root@web02 web02]# touch /tmp/check_{1..10}.txt
[root@web02 web02]# ls -l /tmp/check_[0-9].txt
-rw-r--r-- 1 root root 0 Jul 6 12:34 /tmp/check_1.txt
-rw-r--r-- 1 root root 0 Jul 6 12:34 /tmp/check_2.txt
-rw-r--r-- 1 root root 0 Jul 6 12:34 /tmp/check_3.txt
-rw-r--r-- 1 root root 0 Jul 6 12:34 /tmp/check_4.txt
-rw-r--r-- 1 root root 0 Jul 6 12:34 /tmp/check_5.txt
-rw-r--r-- 1 root root 0 Jul 6 12:34 /tmp/check_6.txt
-rw-r--r-- 1 root root 0 Jul 6 12:34 /tmp/check_7.txt
-rw-r--r-- 1 root root 0 Jul 6 12:34 /tmp/check_8.txt
-rw-r--r-- 1 root root 0 Jul 6 12:34 /tmp/check_9.txt
[root@web02 web02]# ls -l /tmp/check_[0-9][0-9].txt
-rw-r--r-- 1 root root 0 Jul 6 12:34 /tmp/check_10.txt
正则表达式表格
https://blog.driverzeng.com/4re/
用户名:driverzeng
密码:123@qqdiancom
正则表达式注意事项
-
1.所有符号皆为英文符号
-
2.使用三剑客时加引号
-
3.注意字符集,如果出现字符集问题,那么将字符集修改为C(小概率事件)
-
4.像素眼(空格,换行符,tab键)
-
5.测试的时候,推荐使用grep -E或者egrep,因为过滤出来的内容会加颜色
[root@web02 ~]# cat 1.txt
/tmp /check_1.txt
/tmp /check_1.txt
[root@web02 ~]# awk '/\t/{print}' 1.txt teb键
/tmp /check_1.txt
[root@web02 ~]# awk '/ /{print}' 1.txt 空格
/tmp /check_1.txt
grep -E与grep的区别
. 任意字符
.* 匹配所有内容
grep -o '.' /etc/passwd
正则表达式的修饰符(标记)
- 用来做标记的
标记也称为修饰符,正则表达式的标记用于指定额外的匹配策略。
标记不写在正则表达式里,标记位于表达式之外,格式如下:
/pattern/flags
/正则表达式/标记
-----------------------------g---------------------------------
%s###g
sed 's###g'
[root@web02 ~]# cat 1.txt
root
ROOT
[root@web02 ~]# vim 1.txt
[root@web02 ~]# sed 's#root#ll#g' 1.txt
ll ll
ROOT
[root@web02 ~]# sed 's#root#ll#' 1.txt
ll root
ROOT
-----------------------------m---------------------------------
在Linux中,正则表达式修饰符m(多行模式)用于指定多行文本匹配模式。当使用m修饰符时,某些元字符(如^和$)的行为会发生变化,以实现跨越多行进行匹配。
具体来说,在m修饰符下,以下元字符的含义会发生改变:
^(脱字符):通常情况下,^匹配文本的开头。在m修饰符下,^将匹配每一行的开头。
$(美元符号):通常情况下,$匹配文本的结尾。在m修饰符下,$将匹配每一行的结尾。
.(点号):通常情况下,.匹配除了换行符\n之外的任意字符。在m修饰符下,.将匹配包括换行符在内的任意字符。
这里是一个示例,演示了m修饰符的具体用法:
bash
# 多行匹配示例
text='
Hello
World
'
# 不使用 m 修饰符的正则表达式
echo "$text" | grep '^H.*d$'
# 输出:Hello
# 使用 m 修饰符的正则表达式
echo "$text" | grep -P '(?m)^H.*d$'
# 输出:
# Hello
# World
在上面的示例中,我们使用了两种不同的grep命令来匹配文本。第一个命令grep '^H.*d$'没有使用m修饰符,只匹配了以H开头且以d结尾的文本行,所以只输出了Hello。而第二个命令grep -P '(?m)^H.*d$'使用了m修饰符(通过-P选项启用Perl正则表达式模式),成功地匹配了整个多行文本,并输出了所有匹配的行。
-----------------------------s---------------------------------
sed -i 's#查找内容#替换内容#g' 文件名
正则表达式-元字符
# \t 匹配一个横向制表符 teb键
[root@web02 ~]# echo -e 'adc\t123'
adc 123
# \v 匹配一个垂直制表符
[root@web02 ~]# echo -e 'adc\v123'
adc
123
[root@web02 ~]# echo -e 'adc\v123\v456'
adc
123
456
# \f 换页符
[root@web02 ~]# echo -e 'adc\f123'
adc
123
[root@web02 ~]# echo -e 'adc\f123\f456'
adc
123
456
# \b 匹配一个单词边界,也就是指单词和空格间的位置,例如: 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的'er'
[root@web02 ~]# grep -E '\bnginx\b' /etc/passwd
nginx:x:998:996:Nginx web server:/var/lib/nginx:/sbin/nologin
[root@web02 ~]# grep -E 'nginx' /etc/passwd
nginx:x:998:996:Nginx web server:/var/lib/nginx:/sbin/nologin
nginx1:x:1000:1000::/home/nginx1:/bin/bash
nginx2:x:1001:1001::/home/nginx2:/bin/bash
# \B 匹配非单词边界,例如:'er\B' 能匹配 "verb" 中的'er',但不能匹配"never" 中的'er'
# nginx的两包都带带东西才能被匹配出来
[root@web02 ~]# grep -E '\Bnginx\B' /etc/passwd
1nginx23:x:1003:1003::/home/1nginx23:/bin/bash
[root@web02 ~]# grep -E 'nginx\B' /etc/passwd
nginx1:x:1000:1000::/home/nginx1:/bin/bash
nginx2:x:1001:1001::/home/nginx2:/bin/bash
1nginx23:x:1003:1003::/home/1nginx23:/bin/bash
# \d 匹配一个数字字符
匹配从 0 到 9 中的任意一个数字字符(等价于 [0-9])
[root@web02 ~]# cat 2.txt
1
2
3
4
5
[root@web02 ~]# grep -P '\d' 2.txt
1
2
3
4
5
[root@web02 ~]# grep -E '\d' 2.txt
# \n 换行符
[root@web02 ~]# echo -e 'a\nb'
a
b
# \r 回车
[root@web02 ~]# echo -e 'a\rb'
b
# \w 匹配包括下划线的任意字符 (^[A-Z a-z 0-9])
[root@web02 ~]# cat 2.txt
1
2
3
4
5
A
s
a
Z
[root@web02 ~]# grep -P '\w' 2.txt
1
2
3
4
5
A
s
a
Z
# \W 匹配非单词字符串 (^[A-Z a-z 0-9])
[root@web02 ~]# cat 2.txt
1
2
3
4
5
A
s
a
Z
#
$
%
!
[root@web02 ~]# grep -P '\W' 2.txt
#
$
%
!
# \s 匹配任何空白字符,包括空格、制表符、换页符等等(等价于[ \f\n\r\t\v])
[root@web02 ~]# grep -P '\s' 2.txt
# \S 匹配任何非空白字符(等价于[^\f\n\r\t\v])
[root@web02 ~]# grep -P '\S' 2.txt
1
2
3
4
5
A
s
a
Z
#
$
%
!
正则案例
#1.匹配身份证号
##答
[1-9][0-9]{16}([0-9]|x)
#2.匹配手机号
##答
^1[3-9][0-9]{9}
#3.后项引用
(.*) 1
##答
ifconfig eth0 | sed -nr 's#^.*inet (.*) net.*#\1#gp'
#4.给用户传参中间加上空格(后项引用)
echo 123456
sed -r 's#(.*)#<\1>#g'
sed -r 's#(.)#<\1>#g'
##答
echo "123456" | sed 's#\(.\)#\1 #g'
echo {1..10} 带空格的每个都加上<>
##答
echo {1..10} | sed -E 's#([^ ]+)#<\1>#g'
#5.过滤IP
##答
ifconfig eth0 | sed -nr 's#^.*inet (.*) net.*#\1#gp'
10.0.0.8
#6.过滤文件中,oldboy和oldbey的内容
[root@web02 ~]# cat 1.txt
oldboy 123
oldbey 456
oldbyy
oldbee
newboy
##答
[root@web02 ~]# grep -E '(\boldboy\b)|(\boldbey\b)' 1.txt
oldboy 123
oldbey 456
#7.统计上面文件的单词数量
##答
[root@web02 ~]# grep -E '(.*\b)' 1.txt |wc -l
5
#8.统计上面文件的字母数量
##答
[root@web02 ~]# grep -o '[a-z]' 1.txt | wc -l
30
#9.取出下面的指定内容
19:09:03 up 735 days, 23:12, 2 users, load average: 0.00, 0.03, 0.05
19:09:42 up 10:20, 3 users, load average: 0.00, 0.02, 0.05
19:11:24 up 0 min, 1 user, load average: 0.31, 0.08, 0.03
# 如何截取上面的登录用户数?
##答
[root@web02 ~]# sed -r 's#.* (.*) user.*#\1#g' 1.txt
2
3
1
# 如何截取上面的开机时间?
##答
[root@web02 ~]# sed -E 's#^([0-9]{2}:[0-9]{2}:[0-9]{2}).*#\1#g' 1.txt
19:09:03
19:09:42
19:11:24
##答
[root@web02 ~]# sed -r 's#.*up ([^,]+),.*#\1#g' 1.txt
735 days
10:20
0 min
## 因为在Linux中,我们目前只能使用awk grep sed取,而且支持的正则也是基础正则和扩展正则
## 但是有些元字符,基础和扩展正则也不支持,我们只能使用其他语言的正则,比如python
## 于是,在grep命令中,提供了一个选项叫做 -P 这个选项的作用就是,使用perl语言的正则
uptime| grep -Po '[0-9]+(?= user)'
uptime|grep -Po '\d+(?= user)'
uptime|grep -Po '(?<=up).*(?=[0-9] user)'
uptime|grep -Po '(?<=up).*(?=\d user)'