首页 > 系统相关 >Linux Shell编程--正则表达式、grep、sed、awk

Linux Shell编程--正则表达式、grep、sed、awk

时间:2024-08-10 10:23:35浏览次数:7  
标签:bin Shell grep centos -- passwd sed awk root

前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除!

一、正则表达式

1、正则表达式定义

1.1、简介

正则表达式是一种强大的文本模式匹配工具,用于搜索、替换或分割字符串。在Shell脚本中,正则表达式通常与grep、sed和awk等工具一起使用。

1.2、层次分类

  • 基础正则表达式
  • 扩展正则表达式
  • 编程语言支持的高级正则表达式

1.3、linux三剑客(grep sed awk)支持的正则表达式

支持正则的shell命令正则类型
grep默认使用基本正则表达式(BRE)(要使用扩展正则需要加转义字符)
egrep 或 grep -E使用扩展的正则表达式(ERE)
sed默认使用基本正则表达式(BRE)
awk使用扩展正则表达式(ERE)

2、基础正则表达式

基础正则表达式是常用的正则表达式部分

元字符含义
\表示转义字符,去掉特殊符号的特殊含义
.匹配任意单个字符
^匹配字符串开头的位置
$匹配字符串末尾的位置
*匹配前面的字符出现0~+∞
[list]匹配list列表中的一个字符(列表中只要有一个符合即可)
[^list]匹配任意非list列表中的一个字符
{n}匹配前面的子表达式n次
{n,}匹配前面的子表达式最少n次
{,n}匹配前面的子表达式最多n次
{n,m}匹配前面的子表达式n到m次
[ ]代表单个字符
\?1次或0次
^$空行
.*1~+∞

3、扩展正则表达式

支持awk和egrep使用,如果grep和sed想要正常使用(grep -E sed -r)

元字符作用含义
+匹配前面子表达式1次及以上
匹配前面子表达式0次或者1次
()将括号中的字符串作为一个整体
|以"或"的方式匹配字符串

二、使用 grep

grep命令用于搜索文件或标准输入,以查找匹配特定模式的行。

 grep 'pattern' filename
选项作用
-i忽略大小写
-v显示不包含匹配行的文本
-r递归地搜索目录
-n显示匹配行的行号
-w只匹配整个单词
-o仅显示匹配的部分
-e使用多个模式
-f从文件中读取模式
-v仅显示匹配的行数

egrep 支持正则表达式的拓展元字符

  egrep '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}' file1.txt

1、基础正则匹配示例

1.1、运用正则,判断需要[[ ]]

 [root@centos ~]# num1=1
 # 检查变量$num1是否只包含数字
 [root@centos ~]# [[ $num1 =~ ^[0-9]+$ ]] && echo "yes" || echo "no"
 yes
 [root@centos ~]# num3=1b1
 [root@centos ~]# [[ $num3 =~ ^[0-9]+$ ]] && echo "yes" || echo "no"
 no
 # 检查变量 $num 是否是一个有效的数字,可以是整数或者小数
 [root@centos ~]# [[ $num =~ ^[0-9]\.[0-9]+$ || $num =~ ^[0-9]+$ ]] && echo "yes" || echo "no"

1.2、* 匹配签到符0个或多个

 [root@centos ~]# useradd abrt
 [root@centos ~]# grep 'abc*' /etc/passwd
 abrt:x:173:173::/etc/abrt:/sbin/nologin

1.3、\< 词首定位符号\ >词尾定位符号

 [root@centos ~]# cat jack.txt 
 Jack JACK JAck jackly
 :% s/\<[Jj]ack\>/123/g

1.4、^以什么开头

 [root@centos ~]# grep '^root' /etc/passwd
 root:x:0:0:root:/root:/bin/bash

1.5、$以什么结尾

 [root@centos ~]# grep 'bash$' /etc/passwd
 root:x:0:0:root:/root:/bin/bash
 X:x:1000:1000:Lee:/home/X:/bin/bash
 mysql:x:1001:1001::/home/mysql:/bin/bash

1.6、匹配单个字符

 [root@centos ~]# grep 'r..r' /etc/passwd
 operator:x:11:0:operator:/root:/sbin/nologin
 saslauth:x:995:76:Saslauthd user:/run/saslauthd:/sbin/nologin
 [root@centos ~]# grep 'r.t' /etc/passwd
 operator:x:11:0:operator:/root:/sbin/nologin
 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

1.7、.* 任意多个字符

 [root@centos ~]# 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
 ...

1.8、[] 匹配方括号中的任意一个字符

 [root@centos ~]# grep 'Root' /etc/passwd
 [root@centos ~]# grep '[Rr]oot' /etc/passwd
 root:x:0:0:root:/root:/bin/bash
 operator:x:11:0:operator:/root:/sbin/nologin

1.9、[ - ] 匹配指定范围内的一个字符

 [root@centos ~]#  grep [a-z]oot /etc/passwd
 root:x:0:0:root:/root:/bin/bash
 operator:x:11:0:operator:/root:/sbin/nologin
 setroubleshoot:x:994:991::/var/lib/setroubleshoot:/sbin/nologin

1.10、[^] 匹配不在指定组内的字符,非的意思

^在[]内表示取反,^在[]外表示以什么开头

 [root@centos ~]# grep '[^0-9]oot' /etc/passwd
 root:x:0:0:root:/root:/bin/bash
 operator:x:11:0:operator:/root:/sbin/nologin
 setroubleshoot:x:994:991::/var/lib/setroubleshoot:/sbin/nologin
 [root@centos ~]# grep '[^0-9A-Z]oot' /etc/passwd
 root:x:0:0:root:/root:/bin/bash
 operator:x:11:0:operator:/root:/sbin/nologin
 setroubleshoot:x:994:991::/var/lib/setroubleshoot:/sbin/nologin
 [root@centos ~]#  grep '[^0-9A-Za-z]oot' /etc/passwd
 [root@centos ~]# useradd Root
 useradd: user 'Root' already exists
 [root@centos ~]# grep '[a-Z]oot' /etc/passwd
 root:x:0:0:root:/root:/bin/bash
 operator:x:11:0:operator:/root:/sbin/nologin
 setroubleshoot:x:994:991::/var/lib/setroubleshoot:/sbin/nologin
 Root:x:1002:1002::/home/Root:/bin/bash
 [root@centos ~]# grep '^[rc]oot' /etc/passwd
 root:x:0:0:root:/root:/bin/bash

1.11、\(\)匹配后的标签

2、扩展正则匹配示例

2.1、+ 匹配一个或多个前导字符

 [root@centos ~]# egrep 'ro+t' /etc/passwd
 root:x:0:0:root:/root:/bin/bash
 operator:x:11:0:operator:/root:/sbin/nologin

2.1、? 匹配零个或一个前导字符

 [root@centos ~]# egrep 'ro?t' /etc/passwd
 abrt:x:173:173::/etc/abrt:/sbin/nologin

2.2、a|b 匹配a或b

 [root@centos ~]# netstat -anlp|egrep ':80|:22'
 [root@centos ~]# egrep 'root|Root' /etc/passwd
 root:x:0:0:root:/root:/bin/bash
 operator:x:11:0:operator:/root:/sbin/nologin
 Root:x:1002:1002::/home/Root:/bin/bash

2.3、x{m} 字符x重复m次

 [root@centos ~]# egrep 'o{2}' a.txt
 loove
 looooove
 [root@centos ~]# egrep 'o{2,}' a.txt
 loove
 looooove
 [root@centos ~]# egrep 'o{6,7}' a.txt

三、sed

sed流编辑器)用于对文本进行过滤和替换。

sed 's/pattern/replacement/' filename

1、常用选项与命令

1.1、常用选项

选项作用
-n使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN的资料一般都会被列出到屏幕上。但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。
-e直接在指令列模式上进行 sed 的动作编辑;
-f直接将 sed 的动作写在一个档案内, -f filename 则可以执行 filename 内的sed 动作
-rsed 的动作支援的是延伸型正规表示法的语法。(预设是基础正规表示法语法)
-i直接修改读取的档案内容,而不是由屏幕输出

1.2、常用命令

命令作用
a新增, a 的后面可以接字串,而这些字串会在新的一行出现
c取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
d删除
i插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行)
p列印,亦即将某个选择的资料印出。通常 p 会与参数 sed -n 一起
s取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g

2、基本用法

默认会把文件内容全部输出到屏幕中,下面笔记进行对此进行了省略;可加-n参数进行安静模式,并且sed操作默认不会修改原文件内容

# 示例文件:file1.txt
John Daggett, 341 King Road, Plymouth MA
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post Road, Sudbury MA
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston MA

2.1、用Massachusetts替换MA:

[root@centos ~]# sed 's/MA/Massachusetts/' file1.txt

2.2、使用多重指令:

[root@centos ~]# sed 's/MA/Massachusetts/ ; s/PA/Pennsylvania/' file1.txt

2.3、使用脚本文件

[root@centos ~]# cat namestate 
s/MA/Massachusetts/
s/PA/Pennsylvania/
s/CA/California/
s/VA/Virginia/
s/OK/Oklahoma/
[root@centos ~]# sed -f namestate file1.txt 

2.4、保存输出

[root@centos ~]# sed -f namestate file1.txt > newfile.txt

2.5、阻止输入行自动显示

[root@centos ~]# sed -n 's/MA/Massachusetts/p' file1.txt

3、sed流编辑器用法及解析

sed: stream editor(流编辑器)的缩写. 它们最常见的用法是进行文本的替换.;

3.1、删除某行

[root@centos ~]# sed '1d' filename             	# 删除第一行 
[root@centos ~]# sed '$d' filename             	# 删除最后一行
[root@centos ~]# sed '1,2d' filename        	# 删除第一行到第二行
[root@centos ~]# sed '2,$d' filename         	# 删除第二行到最后一行
[root@centos ~]# sed '1~2d' passwd			    # 删除奇数行
[root@centos ~]# sed '0~2d' passwd 				# 删除偶数行
[root@centos ~]# sed '/^$/d' filename			# 删除文件中的空行

3.2、显示某行

[root@centos ~]# sed -n '1p' filename           #显示第一行 
[root@centos ~]# sed -n '$p' filename           #显示最后一行
[root@centos ~]# sed -n '1,2p' filename        #显示第一行到第二行
[root@centos ~]# sed -n '2,$p' filename        #显示第二行到最后一行

3.3、使用模式进行查询

[root@centos ~]# sed -n '/ruby/p' filename    #查询包括关键字ruby所在所有行
[root@centos ~]# sed -n '/\$/p' filename    #查询包括关键字$所在所有行,使用反斜线\屏蔽特殊含

3.4、增加一行或多行字符串

[root@centos ~]# cat file.txt 
Hello!
Knowledge is power!
Every cloud has a silver lining
# 第一行后增加字符串"welcomto Hunan!"
[root@centos ~]# sed '1a welcom to Hunan!' file.txt
Hello!
welcom to Hunan!
Knowledge is power!
Every cloud has a silver lining
# 第一行到第三行后增加字符串"welcome to Hunan!"
[root@centos ~]# sed '1,3a welcome to Hunan!' file.txt
Hello!
welcome to Hunan
Knowledge is power!
welcome to Hunan
Every cloud has a silver lining
welcome to Hunan
# [root@centos ~]# sed '1a welcome to Hunan\nPassion!' file.txt
Hello!
welcome to Hunan
Passion!
Knowledge is power!
Every cloud has a silver lining第一行后增加多行,使用换行符\n

3.5、代替一行或多行

# 第一行代替为Hi
[root@centos ~]# sed '1c Hi' file.txt
Hi
Knowledge is power!
Every cloud has a silver lining
# 第一行到第二行代替为Hi
[root@centos ~]# sed '1,2c Hi' file.txt
Hi
Every cloud has a silver lining

3.6、 替换一行中的某部分

格式: sed ‘s/要替换的字符串/新的字符串/g’ (要替换的字符串可以用正则表达式)

[root@centos ~]# sed -n '/is/p' file.txt | sed 's/is/are/g'	# 替换is为are
Knowledge are power!
[root@centos ~]# sed -n '/is/p' file.txt | sed 's/is//g'	# 删除is
Knowledge  power!
# 忽略大小写替换
sed 's/pattern/replace_string/gi' filename

# g标记可以使sed匹配第N次以后的字符被替换
echo "thisthisthisthis" | sed 's/this/THIS/2g'

# sed中的分隔符可以替换成别的字符, 因为s标识会认为后面的字符为分隔符
sed 's:text:replace_text:'
sed 's|text|replace_text|'

3.7、插入

# 在文件file.txt中最后一行插入"bye"
[root@centos ~]# sed -i '$a bye' file.txt	
[root@centos ~]# cat file.txt 
Hello!
Knowledge is power!
Every cloud has a silver lining
bye

3.8、注意点

由于在使用 -i 参数时比较危险, 所以我们在使用i参数时在后面加上.bak就会产生一个备份的文件, 以防后悔:

sed -i.bak 's/pattern/replace_string/' filename

sed如果在脚本中使用的话, 不可避免的要调用变量, 所以以下这种方式可以用来调用变量即' '换成了“”

# text=hello
# echo "hello world" | sed "s/$text/HELLO/"

四、 awk

awk是一个强大的文本处理工具,它使用模式匹配和动作来处理数据。

awk是行处理器: 相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢出或是处理缓慢的问题,

通常用来格式化文本信息

awk处理过程: 依次对每一行进行处理,然后输出 默认分隔符是空格或者tab键

awk '/pattern/ { actions }' filename

1、awk的工作原理

awk -F":" '{print $1,$3}' /etc/passwd

(1)awk使用一行作为输入,并将这一行赋给变量$0,每一行可称作为一个记录,以换行符结束

(2)然后行被:分解成字段,每个字段存储在已编号的变量中,从$1开始

(3)awk如何知道空格来分隔字段的呢?因为有一个内部变量FS来确定字段分隔符,初始时,FS赋为空格或者是tab

(4)awk打印字段时,将以设置的方法,使用print函数打印,awk在打印的字段间加上空格,因为​3间有一个,逗号。逗号比较特殊,映射为另一个变量,成为输出字段分隔符OFS,OFS默认为空格

(5)awk打印字段时,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程持续到处理文件结束。

2、BEGIN与END

BEGIN {} {}:在处理任何输入之前执行的代码块

END{}:在处理完所有输入之后执行的代码块

[root@centos ~]# awk 'BEGIN{print 1/2} {print "ok"} END{print "-----"}' /etc/hosts
0.5
ok
ok
-----
# 首先打印 1/2 的结果,然后打印 "ok",接着对 /etc/hosts 文件的每一行执行 {print "ok"},最后在处理完所有行之后打印 "----"

3、常用选项与示例

选项作用
FS指定每行文本的字段分隔符,默认为空格或制表位
OFS输出字段分隔符
NF当前处理的行的字段个数
NR当前处理的行的行号(序数)
$0当前处理的行的整行内容
$n当前处理行的第 n 个字段(第 n 列)
FILENAME被处理的文件名
RS“行“分割符,awk从文件上读取资料时,将根据RS的定义把资料切割成许多条记录; wak一次仅读入一条记录,以进行处理,预设值是” \n “
ORS输出记录分隔符

3.1、FS(输入字段分隔符)

# 输出 /etc/passwd 文件中每一行的第一个字段,也就是系统中每个用户的登录名
[root@centos ~]# awk 'BEGIN{FS=":"}{print $1}' /etc/passwd
root
bin
daemon
adm
...

3.2、OFS(输出字段分隔符)

# 输出 /etc/passwd 文件中每一行的前两个字段,格式为 用户名..加密密码
[root@centos ~]# awk 'BEGIN{FS=":";OFS=".."}{print $1,$2}' /etc/passwd
root..x
bin..x
daemon..x
adm..x
...

3.3、NR (记录编号)

当awk将行为记录时, 该变量相当于当前行号

[root@centos ~]# awk -F: '{print NR,$0}' a.txt file1.txt
1 love
2 love.
3 loove
4 looooove
5
6 isuo
7 IPADDR=192.168.6.5
8 hjahj123
9 GATEWAY=192.168.1.1
10 NETMASK=255.255.255.0
11 DNS=114.114.114.114

3.4、FNR(记录编号)

当awk将行为记录时, 该变量相当于当前行号(不同文件分开)

[root@centos ~]# awk -F: '{print FNR,$0}' a.txt file1.txt
1 love
2 love.
3 loove
4 looooove
5
1 isuo
2 IPADDR=192.168.6.5
3 hjahj123
4 GATEWAY=192.168.1.1
5 NETMASK=255.255.255.0
6 DNS=114.114.114.114

3.5、RS(输入记录分隔符)

[root@centos ~]# cat 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
[root@centos ~]# awk -F: 'BEGIN{RS="bash"} {print $0}' passwd
root:x:0:0:root:/root:/bin/

bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

3.6、ORS(输出记录分隔符)

[root@centos ~]# awk -F: 'BEGIN{ORS=" "} {print $0}' 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

4、练习

(1)将文件合并为一行

awk 'BEGIN{ORS="" } {print $0}' /etc/passwd

(2)把一行内容分为多行

[root@centos ~]# cat d.txt
root:x:0:0:root:/root:/bin/bash
[root@centos ~]# awk 'BEGIN{RS=":"} {print $0}' d.txt
root
x
0
0
root
/root
/bin/bash

5、理解案例

1、打印一个文件中的第2列和第3列

awk '{print $2,$3}' filename

2、打印指定行指定列的某个字符

awk -F":" 'NR==3{ print $7 }' /etc/passwd

3、统计一个文件的行数:

awk '{ print NR}' filename

4、在脚本中, 传递变量到awk中:

# var=1000
# echo | awk -v VARIABLE=$var '{ print VARIABLE }'

5、指定字段分隔符-F或在BEGIN{ FS=":" } :

# awk -F: '{ print $2, $3 }' filename
# awk 'BEGIN{ FS=":" }{ print $2, $3 }' filename

6、在awk中使用for循环 :

# 每行打印两次
[root@centos ~]# awk -F: '{for(i=1;i<=2;i++) {print $0}}' passwd
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
# 分别打印每行每列
[root@centos ~]# awk -F: '{ for(i=1;i<=NF;i++) {print $i}}' passwd
...

7、 在awk中使用if条件判断:

# 显示管理员用户名
[root@centos ~]# awk -F: '{if($3==0) {print $1 " is administrator."}}' /etc/passwd
# 统计系统用户
[root@centos ~]# awk -F":" '{if($3>0 && $3<1000){i++}} END{print i}' /etc/passwd

致谢

在此,我要对所有为知识共享做出贡献的个人和机构表示最深切的感谢。同时也感谢每一位花时间阅读这篇文章的读者,如果文章中有任何错误,欢迎留言指正。 

学习永无止境,让我们共同进步!!

标签:bin,Shell,grep,centos,--,passwd,sed,awk,root
From: https://blog.csdn.net/lerp020321/article/details/141057323

相关文章

  • Docker快速入门指南
    ......
  • MySQL--主从复制
    前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除一、什么是主从复制1、定义主从复制,是用来建立一个和主数据库完全一样的数据库环境,称为从数据库;主数据库一般是准实时的业务数据库。2、作用做数据的热备,作为后备数据库,主数据库服务器故障后,可切......
  • 触想工控设备在工业“无人化”场景的应用
    今年七月,比酷暑更加火爆的,当属频登热搜的武汉无人驾驶出租车“萝卜快跑”——L4级自动驾驶、360°三维感知、AI大模型算法……高端科技与“低价揽客”的反差感使得“萝卜快跑”迅速走红。△图源|萝卜快跑官网平台“萝卜快跑”的神秘面纱“萝卜快跑”无人驾......
  • Cisco ASAv 9.20.3 - 思科自适应安全虚拟设备 (ASAv)
    CiscoASAv9.20.3-思科自适应安全虚拟设备(ASAv)CiscoAdaptiveSecurityVirtualAppliance(ASAv)请访问原文链接:https://sysin.org/blog/cisco-asav/,查看最新版。原创作品,转载请保留出处。思科自适应安全虚拟设备(ASAv):跨物理和虚拟环境扩展安全性思科自适应安全虚......
  • 08-09 题解
    08-09题解A小水题思路假设我们选定了当前子序列的绝对众数\(x\),那么该序列里最多再放\(num_x-1\)个其他数字为了分出最少的子序列,肯定要让每个子序列在拥有绝对众数的同时能消化尽量多的其他数字由此,可以得到一个贪心策略:每次取出出现次数最多的一个数字,消掉出现......
  • ABC 365
    赛时通过:A、B、C。赛后补题:D、E。A依题判断即可。#include<bits/stdc++.h>usingnamespacestd;inty;intmain(){ cin>>y; if(y%4!=0)cout<<365; if(y%4==0&&y%100!=0)cout<<366; if(y%100==0&&y%400!=0)cout<<365; if(y%400==0)......
  • 前端黑科技:使用 JavaScript 实现网页扫码功能
    在数字化时代,二维码已经渗透到我们生活的方方面面。从移动支付到产品溯源,二维码凭借其便捷性和高效性,成为了信息传递的重要载体。而随着前端技术的不断发展,我们甚至可以使用JavaScript在网页端实现二维码扫描功能,为用户提供更加便捷的操作体验。本文将带您深入了解如何使用Jav......
  • CryptoHouse:由 ClickHouse 和 Goldsky 支持的免费区块链分析服务(ClickHouse 博客)
    我们很高兴地宣布CryptoHouse,在crypto.clickhouse.com上可访问,这是一个由ClickHouse提供支持的免费区块链分析服务。https://crypto.clickhouse.com/现有的公共区块链分析服务通常需要定时、异步查询,而ClickHouse提供实时分析,通过即时查询响应来普及访问权限。用户可以......
  • proteus 中单片机串口仿真实验
    位置:                    连线如图:问题解决在进行仿真的时候,可能不会出现terminal显示框,可以在菜单栏debug->virtualterminal来让它显示:如果visualterminal显示的是乱码,我们就需要根据实际情况修改单片机时钟频率,双击单片机,在......
  • 接收用户的输入
    staticvoidMain(string[]args){Console.WriteLine("美女,你喜欢吃什么水果?");stringstrFruit=Console.ReadLine();//接收用户输入的字符串;Console.WriteLine("这么巧吗,我也喜欢吃"+strFruit+";");Con......