shell编程之正则表达式与文本处理器

文章目录

  • 一、正则表达式
    • 1.正则表达式定义
    • 2.元字符
    • 3.表示次数
    • 4.位置锚定
    • 5.分组或其他
    • 6. 扩展正则表达式
  • 二、文本处理工具
    • 1.grep
    • 2.sed
      • 基本用法
      • 搜索和替代
    • 3.awk


一、正则表达式

1.正则表达式定义

正则表达式,又称正规表达式、常规表达式
使用字符串来描述、匹配一系列符合某个规则的字符串

正则表达式组成
普通字符:
大小写字母、数字、标点符号及一些其他符号
元字符:
在正则表达式中具有特殊意义的专用字符

2.元字符

. 匹配任意单个字符,可以是一个汉字
[] 匹配指定范围内的任意单个字符,示例:[zhou] [0-9] [] [a-zA-Z]
[^] 匹配指定范围外的任意单个字符,示例:[^zhou] [^a.z] a.z

[:alnum:] 字母和数字
[:alpha:] 代表任何英文大小写字符,亦即 A-Z, a-z
[:lower:] 小写字母,示例:[[:lower:]],相当于[a-z]
[:upper:] 大写字母
[:blank:] 空白字符(空格和制表符)
[:space:] 包括空格、制表符(水平和垂直)、换行符、回车符等各种类型的空白,比[:blank:]包含的范围广
[:cntrl:] 不可打印的控制字符(退格、删除、警铃…)
[:digit:] 十进制数字
[:xdigit:]十六进制数字
[:graph:] 可打印的非空白字符
[:print:] 可打印字符
[:punct:] 标点符号
\w #匹配单词构成部分,等价于[[:alnum:]]
\W #匹配非单词构成部分,等价于[^
[:alnum:]]
\S #匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\s #匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。注意
Unicode 正则表达式会匹配全角空格符

3.表示次数

* #匹配前面的字符任意次,包括0次
.* #任意长度的任意字符
? #匹配其前面的字符出现0次或1次,即:可有可无
+ #匹配其前面的字符出现最少1次,即:肯定有且 >=1 次
{n} #匹配前面的字符n次
{m,n} #匹配前面的字符至少m次,至多n次
{,n} #匹配前面的字符至多n次,<=n
{n,} #匹配前面的字符至少n次

代表前面的o出现2次
[root@localhost ~]# echo google |grep ‘go\{2\}gle’
google
代表前面的o出现2次以上
[root@localhost ~]# echo gooooogle |grep ‘go\{2,\}gle’
gooooogle
代表前面的o出现2次以上5次以下
[root@localhost ~]# echo gooooogle |grep ‘go\{2,5\}gle’
gooooogle
[root@localhost ~]# echo goooooogle |grep ‘go\{2,5\}gle’
[root@localhost ~]#
表示0次到任意次
[root@localhost ~]# echo goooooogle |grep ‘go*gle’
goooooogle
[root@localhost ~]# echo ggle |grep “go*gle”
ggle
[root@localhost ~]# echo gggle |grep “go*gle”
gggle
.*代表任意匹配所有
[root@localhost ~]# echo gdadadadgle |grep “g.*gle”
gdadadadgle
\?一次或者0次
[root@localhost ~]# echo ggle |grep “go\?gle”
ggle
[root@localhost ~]# echo gogle |grep “go\?gle”
gogle
一个以上
[root@[root@localhost ~]# echo google |grep “go\+gle”
google
[root@localhost ~]# echo gogle |grep “go\+gle”
gogle
[root@localhost ~]# echo ggle |grep “go\+gle”
[root@localhost ~]# echo google |grep “go\?gle”

4.位置锚定

^ #行首锚定, 用于模式的最左侧
$ #行尾锚定,用于模式的最右侧
^PATTERN$ #用于模式匹配整行 (单独一行 只有root)
^$ #空行
^[[:space:]]*$ #空白行
\< 或 \b #词首锚定,用于单词模式的左侧(连续的数字,字母,下划线都算单词内部)
\> 或 \b #词尾锚定,用于单词模式的右侧
\ #匹配整个单词

过滤出不是以#号开头的非空行
[root@localhost ~]#grep “^[^#]” /etc/fstab

过滤出空白行
[root@localhost ~]#grep “^[[:space:]]*$” /etc/fstab

词首锚定
[root@localhost ~]#echo hello-123 |grep “\<123”
hello-123
[root@localhost ~]#echo hello 123 |grep “\<123”
hello 123

匹配整个单词
[root@localhost html]# echo hello 123 |grep “
hello 123
[root@localhost html]# echo hello 123 |grep “
[root@localhost html]#

5.分组或其他

分组:() 将多个字符捆绑在一起,当作一个整体处理,如:(root)+

后向引用:分组括号中的模式匹配到的内容会被正则表达式引擎记录于内部的变量中,这些变量的命名

方式为: \1, \2, \3, …

\1 表示从左侧起第一个左括号以及与之匹配右括号之间的模式所匹配到的字符

[root@localhost ~]#ifconfig ens33|grep netmask|grep -o ‘\([0-9]\{1,3\}\.\)\{3\}[0-9]\{3\}’
192.168.47.103
192.168.47.255
[root@localhost ky15]#ifconfig ens33 |grep netmask|grep -Eo ‘([0-9]{1,3}.){4}’
[root@localhost html]# ifconfig ens33 |grep netmask|egrep -o ‘([0-9]{1,3}.){4}’

6. 扩展正则表达式

表示次数

* 匹配前面字符任意次
? 0或1次
+ 1次或多次
{n} 匹配n次
{m,n} 至少m,至多n次
{,n} #匹配前面的字符至多n次,<=n,n可以为0
{n,} #匹配前面的字符至少n次,<=n,n可以为0

表示分组

() 分组
分组:() 将多个字符捆绑在一起,当作一个整体处理,如:(root)+
后向引用:\1, \2, …
| 或者
a|b #a或b
C|cat #C或cat
(C|c)at #Cat或cat

使用扩展正则表达式就需要
egrep
grep -E
sed -r

二、文本处理工具

1.grep

grep [选项]… 查找条件 目标文件

  • -i:查找时忽略大小写
  • -v:反向查找,输出与查找条件不相符的行
  • -o 只显示匹配项
  • -f 对比两个文件的相同行
  • -c 匹配的行数([root@localhost ky15]# grep -c root passwd 2)

2.sed

sed 即 Stream EDitor,和 vi 不同,sed是行编辑器
Sed是从文件或管道中读取一行,处理一行,输出一行;再读取一行,再处理一行,再输出一行,直到最后一行。每当处理一行时,把当前处理的行存储在临时缓冲区中,称为模式空间(PatternSpace),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。一次处理一行的设计模式使得sed性能很高,sed在读取大文件时不会出现卡顿的现象。如果使用vi命令打开几十M上百M的文件,明显会出现有卡顿的现象,这是因为vi命令打开文件是一次性将文件加载到内存,然后再打开。Sed就避免了这种情况,一行一行的处理,打开速度非常快,执行速度也很快

基本用法

常用选项:
-n 不输出模式空间内容到屏幕,即不自动打印
-e 多点编辑
-f FILE 从指定文件中读取编辑脚本
-r, -E 使用扩展正则表达式
-i.bak 备份文件并原处编辑
-s 将多个文件视为独立文件,而不是单个连续的长文件流

输入一行打印一行
[root@localhost html]# sed ‘’
a
a
a
a
d
d
c
c
查看文件内容
[root@localhost html]# echo “123” > /opt/1.txt
[root@localhost html]# sed ‘’ /opt/1.txt
123

只显示第二行
[root@localhost html]# ifconfig ens33
ens33: flags=4163 mtu 1500
inet 192.168.47.103 netmask 255.255.255.0 broadcast 192.168.47.255
inet6 fe80::88a:9ccd:bb0f:c5f1 prefixlen 64 scopeid 0x20
ether 00:0c:29:12:f9:06 txqueuelen 1000 (Ethernet)
RX packets 734942 bytes 1088384896 (1.0 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 268553 bytes 16660890 (15.8 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

[root@localhost html]# ifconfig ens33 |sed -n 2p
inet 192.168.47.103 netmask 255.255.255.0 broadcast 192.168.47.255

插入行和替换行
[root@localhost html]# seq 3 |sed ‘2aabc’
1
2
abc
3
[root@localhost html]# seq 3 |sed ‘2iabc’
1
abc
2
3
[root@localhost html]# seq 3 |sed ‘2cabc’
1
abc
3

搜索和替代

s/pattern/string/修饰符 查找替换,支持使用其它分隔符,可以是其它形式:s@@@,s###
替换修饰符:
g 行内全局替换
p 显示替换成功的行
w /PATH/FILE 将替换成功的行保存至文件中
I,i 忽略大小写

替换
[root@localhost html]# seq 3 |sed -r ‘s/1/2/’
2
2
3

分组
[root@localhost ~]#echo 123xyzabc |sed -r ‘s/(123)(xyz)(abc)/\1\2/’
123xyz

多点编辑,忽略大小写
[root@localhost data]# cat 1.txt 2.txt
123
456
abc
def
[root@localhost data]# sed -i -e ‘s/123/cba/’ 1.txt -e ‘s/abc/789/’ 2.txt
[root@localhost data]# cat 1.txt 2.txt
cba
456
789
def

3.awk

前面提到 sed 命令常用于一整行的处理,而 awk 比较倾向于将一行分成多个“字段”然后再进行处理,且默认情况下字段的分隔符为空格或 tab 键。awk 执行结果可以通过 print 的功能将字段数据打印显示。

[root@localhost ~]#awk ‘’
空没有效果

[root@localhost ~]#awk ‘{print}’
在打印一遍
dd
dd

[root@localhost ~]#awk ‘{print “hello”}’
字符串需要添加双引号,单引号已被使用
1
hello
1
hello

[root@localhost ky15]#awk ‘BEGIN {print “hello”}’
BEGIN比较特殊只打一行
hello

[root@localhost ~]#awk -F: ‘{print “root”}’ /etc/passwd
打印root 多少行=passwd里的行数
[root@localhost ky15]#echo {a…b} |awk ‘{print $1}’
连续的空白符也可以
a

[root@localhost ky15]#df|awk ‘{print $5}’
#分区利用率
已用%
8%
0%
0%
1%
0%
4%
0%
1%

[root@localhost ky15]#cat /etc/passwd|awk -F: ‘{print $1,$3}’ |tail -3
指定冒号作为分隔符,打印第一列和第三列

[root@localhost ky15]#cat /etc/passwd|awk -F: ‘{print $1":"$3}’ |tail -3
用冒号分隔开

[root@localhost ky15]#cat /etc/passwd|awk -F: ‘{print $1"\t"$3}’ |tail -3

取 ip地址

[root@localhost ky15]#ifconfig ens33|sed -n ‘2p’ |awk ‘{print $2}’

[root@localhost ky15]#hostname -I|awk {print $1}
192.168.91.100 192.168.122.1

[root@localhost ~]#wc -l /etc/passwd
42 /etc/passwd
[root@localhost ~]#awk -F: ‘{print $0}’ /etc/passwd
$0代表全部元素
[root@localhost ~]#awk -F: ‘{print $1}’ /etc/passwd
代表第一列
[root@localhost ~]#awk -F: ‘{print $1,$3}’ /etc/passwd
代表第一第三列
[root@localhost ky15]#awk ‘/^root/{print}’ passwd
已root为开头的行
[root@localhost ky15]#grep -c “/bin/bash$” passwd
统计当前已/bin/bash结尾的行
2

BEGIN{}模式表示,在处理指定的文本前,需要先执行BEGIN模式中的指定动作; awk再处理指定的文本,之后再执行END模式中的指定动作,END{}语句中,一般会放入打印结果等语句。

[root@localhost data]# awk ‘BEGIN {x=0};//bin/bash$/;{x++};END{print x}’ /data/passwd
root: x:0:0:root:/root:/bin/bash
wuweide: x:1000:1000:wuweide:/home/wuweide:/bin/bash
42

你可能感兴趣的:(Linux,正则表达式,前端,后端)