Shell语言基本语法总结(5)文本处理之sed

文章目录 九、文本处理之sed 增删改查9.1、查询(重要)9.1.1、np 第n行;n,mp 第n行到m行;n,+mp 第n到n+m行 p取行9.1.2、/

文章目录

  • 九、文本处理之sed 增删改查
    • 9.1、查询(重要)
      • 9.1.1、np 第n行;n,mp 第n行到m行;n,+mp 第n到n+m行 p取行
      • 9.1.2、/查询内容/p 支持正则 查询包含指定内容的行
      • 9.1.3、/开始/, /结束/p 范围查询行
    • 9.2、增加
      • 9.2.1、na 第n行的下一行新增
      • 9.2.1、ni 第n行的上一行新增
      • 9.2.1、nc 第n行新增 相当于替换掉当前行
      • 9.2.1、r 读取并追加
    • 9.3、删除
    • 9.4、修改
    • 9.5、s///g 反向引用 ()
      • 附加:sed命令总结

九、文本处理之sed 增删改查

  • sed命令处理过程按照行为单位,一行一行的处理,直至最后一行结束
  • 工作原理:sed 命令读取当前行到内存中,根据条件进行判断是否符合,若符合则输出改行,继续读下一行;若不符合条件,则直接读取下一行;一行一行的读取,直至数据最后一行,程序结束。

9.1、查询(重要)

  • 命令格式:sed [选项] “条件 命令” 文件
  • 选项
选项解释
-n取消自动打印模式空间(原数据) 一般与p一起使用
-r使用扩展正则表达式
-I忽略大小写
条件解释
n按行号查找 ,第n行
n,m按行号查找 ,第n—m行
n,+m按行号查找 ,第n—n+m行
/n/按内容查找 ,包含n的行
/n/,/m /按内容查找 ,从包含n的行到包含m的行
$最后一行
  • 这些条件查询都可以用户删除和增加用法中
命令解释
p显示print
  • 数据准备
# s.txt 各列含义:姓名 性别 年龄 职业
cxy,male,19,stu
zzf,female,20,actor
zjm,female,22,actor
ycy,female,23,star
cxl,male,24,stu
bl,female,26,star

9.1.1、np 第n行;n,mp 第n行到m行;n,+mp 第n到n+m行 p取行

  • np 打印文件的第三行数据 (-n只显示需求结果)
[hadoop1@hadoop1 test]$ sed -n '3p' s.txt
zjm,female,22,actor
  • n,mp 打印第2到4行数据
[hadoop1@hadoop1 test]$ sed -n '2,4p' s.txt
zzf,female,20,actor
zjm,female,22,actor
ycy,female,23,star
  • n,+mp 打印第2行和往下3行的内容
[hadoop1@hadoop1 test]$ sed -n '2,+3p' s.txt
zzf,female,20,actor
zjm,female,22,actor
ycy,female,23,star
cxl,male,24,stu
  • 获取最后一行内容
[hadoop1@hadoop1 test]$ sed -n '$p' s.txt
bl,female,26,star

9.1.2、/查询内容/p 支持正则 查询包含指定内容的行

  • 查询 cxl 所在行
[hadoop1@hadoop1 test]$ sed -n '/cxl/p' s.txt
cxl,male,24,stu
  • 查询 cxl 或 cxy 所在行
[hadoop1@hadoop1 test]$ sed -n -r '/cxl|cxy/p' s.txt
cxy,male,19,stu
cxl,male,24,stu
  • 分别显示空行和非空行( ! 的妙用)
# 打印原数据
[hadoop1@hadoop1 test]$ echo -e "123\n\n456\n789"
123456
789
# 显示空行
[hadoop1@hadoop1 test]$ echo -e "123\n\n456\n789" | sed -n '/^$/p'# 显示非空行
[hadoop1@hadoop1 test]$ echo -e "123\n\n456\n789" | sed -n '/^$/!p'
123
456
789

9.1.3、/开始/, /结束/p 范围查询行

  • 查询年龄在20—23岁之间的
[hadoop1@hadoop1 test]$ sed -n '/20/,/24/p' s.txt
zzf,female,20,actor
zjm,female,22,actor
ycy,female,23,star
cxl,male,24,stu

9.2、增加

  • 选项:-i 在原文件上增加
命令描述
a 新增当前行下一行新增
i 新增当前行上一行新增
c 新增在n1和n2之间的行
r 追加读取文件并追加文本
  • $a/c/i/r的意思是最后一行

9.2.1、na 第n行的下一行新增

  • 在第二行的下一行插入 xyg,male,20,stu
[hadoop1@hadoop1 test]$ sed '2axyg,male,20,stu' s.txt 
cxy,male,19,stu
zzf,female,20,actor
xyg,male,20,stu
zjm,female,22,actor
ycy,female,23,star
cxl,male,24,stu
bl,female,26,star

9.2.1、ni 第n行的上一行新增

  • 在第二行的上一行插入 xyg,male,20,stu
[hadoop1@hadoop1 test]$ sed '2i xyg,male,20,stu' s.txt
cxy,male,19,stu
xyg,male,20,stu
zzf,female,20,actor
zjm,female,22,actor
ycy,female,23,star
cxl,male,24,stu
bl,female,26,star

9.2.1、nc 第n行新增 相当于替换掉当前行

  • 在第二行插入xyg,male,20,stu
[hadoop1@hadoop1 test]$ sed '2cxyg,male,20,stu' s.txt 
cxy,male,19,stu
xyg,male,20,stu
zjm,female,22,actor
ycy,female,23,star
cxl,male,24,stu
bl,female,26,star

9.2.1、r 读取并追加

  • 把ss.txt文件内容追加到s.txt文件中
[hadoop1@hadoop1 test]$ sed -i '$r ss.txt' s.txt
[hadoop1@hadoop1 test]$ cat s.txt
cxy,male,19,stu
zzf,female,20,actor
zjm,female,22,actor
ycy,female,23,star
cxl,male,24,stu
bl,female,26,star
wo lai dao luan de

9.3、删除

  • 选项:-i 在原文件上删除
脚本命令描述
d 删除后面通常不接任何文本,删除匹配行
  • 删除 wo lai dao luan de 这行
[hadoop1@hadoop1 test]$ sed -i '/wo lai dao luan de/d' s.txt
[hadoop1@hadoop1 test]$ cat s.txt
cxy,male,19,stu
zzf,female,20,actor
zjm,female,22,actor
ycy,female,23,star
cxl,male,24,stu
bl,female,26,star

9.4、修改

  • 选项:-i 在原文件上修改
脚本命令描述
s/原字符/新字符/g新字符替换掉元字符,g表示全局匹配
不加g只会替换掉每行第一个出现的字符;
这里的反斜杠"/"也可以是@,#,*等等 ,只要是三个相同的符号应该就可以。
  • 将s.txt文件中的单个数字替换为null;例如12换为nullnull
# 不加g 只换每行第一个数字
[hadoop1@hadoop1 test]$ sed 's/[0-9]/null/' s.txt
cxy,male,null9,stu
zzf,female,null0,actor
zjm,female,null2,actor
ycy,female,null3,star
cxl,male,null4,stu
bl,female,null6,star
# 加g 凡是数字都替换掉 全局匹配
[hadoop1@hadoop1 test]$ sed  's/[0-9]/null/g' s.txt
cxy,male,nullnull,stu
zzf,female,nullnull,actor
zjm,female,nullnull,actor
ycy,female,nullnull,star
cxl,male,nullnull,stu
bl,female,nullnull,star
  • 将stxt中的两位数替换为null
[hadoop1@hadoop1 test]$ sed -r 's/[0-9]{2}/null/g' s.txt
cxy,male,null,stu
zzf,female,null,actor
zjm,female,null,actor
ycy,female,null,star
cxl,male,null,stu
bl,female,null,star

9.5、s///g 反向引用 ()

  • 上一篇总结的括号区别的时候,() 有两个作用:1️⃣括号里的看作一个整体;2️⃣分组,反向引用。
  • 反向引用:若匹配到的内容有n组,则\n表示引用第 n 组匹配的内容。(一个() 一组)
  • 将 stu_cxl 改为 cxl_stu (\1就是stu,\2就是cxl)
[hadoop1@hadoop1 test]$ echo stu_cxl | sed -r 's#(^.*)_(.*$)#\2_\1#'
cxl_stu
  • 取出ens33的IP网址 inet
# 显示 ens33内容 
[hadoop1@hadoop1 test]$ ifconfig ens33 
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500inet 192.168.1.101  netmask 255.255.255.255  broadcast 192.168.1.101inet6 fd15:4ba5:5a2b:1008:3f68:66f9:e915:7651  prefixlen 64  scopeid 0x0<global>inet6 fe80::c4b6:e442:1b5d:d35d  prefixlen 64  scopeid 0x20<link>ether 00:0c:29:a9:1e:30  txqueuelen 1000  (Ethernet)RX packets 657  bytes 90570 (88.4 KiB)RX errors 0  dropped 0  overruns 0  frame 0TX packets 686  bytes 69105 (67.4 KiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
# ip地址在第二行 2p只取第二行
[hadoop1@hadoop1 test]$ ifconfig ens33 | sed -n '2p'inet 192.168.1.101  netmask 255.255.255.255  broadcast 192.168.1.101
# 我们需要的是inet后面的ip,因此划分为三部分:# (^.*inet )任意字符开头inet 结尾 ,必须写上inet ,因为贪婪匹配,否则会匹配到最后一个空格  \1# (.*) 我们需要的ip地址  \2# ( netmask.*) 地址后面的字符 以 netmask开头,任意字符结尾的  \3      
[hadoop1@hadoop1 test]$ ifconfig ens33 | sed -n '2p'|sed -r 's/(^.*inet )(.*)( netmask.*)/\2/g'
192.168.1.101 # () 里是我们所需要的,不需要的可以不用加括号 因此这里只给ip加了() 它的组为 \1
[hadoop1@hadoop1 test]$ ifconfig ens33 | sed -n '2p'|sed -r 's/^.*inet (.*) netmask.*/\1/g'
192.168.1.101 # 再精简点, 上面用了两次sed 可以合为一个sed命令# -r -n 可以合并成-rn 没有顺序# 2p 打印第二行,中间加上反向向引用之后就是打印第二行符合条件的内容;# 过程:2第二行,执行条件程序s,p打印
[hadoop1@hadoop1 test]$ ifconfig ens33 | sed -rn '2s/^.*inet (.*) n.*/\1/gp'
192.168.1.101 
  • 如图所示正则表示的具体含义及分组情况:
    在这里插入图片描述
  • 取出 /etc/hosts 数字权限
[hadoop1@hadoop1 test]$ stat /etc/hosts文件:"/etc/hosts"大小:224       	块:8          IO 块:4096   普通文件
设备:803h/2051d	Inode:9426263     硬链接:1
权限:(0644/-rw-r--r--)  Uid:(    0/    root)   Gid:(    0/    root)
最近访问:2022-05-26 13:50:32.536298284 +0800
最近更改:2022-05-18 19:21:34.454338769 +0800
最近改动:2022-05-18 19:21:34.456338796 +0800
创建时间:-
# 权限位于第四行 
[hadoop1@hadoop1 test]$ stat /etc/hosts | sed -n '4p'
权限:(0644/-rw-r--r--)  Uid:(    0/    root)   Gid:(    0/    root)
# 只要权限644  ^.*\(0      (.*)      /-.*$
[hadoop1@hadoop1 test]$ stat /etc/hosts | sed -n '4p'| sed -r 's#^.*\(0(.*)/-.*$#\1#g'  
644
# 简写 
[hadoop1@hadoop1 test]$ stat /etc/hosts | sed -rn '4s#^.*\(0(.*)/-.*$#\1#gp'  
644
# 权限 + 具体字母 对)转义不成功 不知什么原因 (\) Uid.*)
[hadoop1@hadoop1 test]$ stat /etc/hosts | sed -rn '4s#^.*(644.*) Uid.*#\1#gp'  
644/-rw-r--r--) 
# 把小括号替换掉为空白
[hadoop1@hadoop1 test]$ stat /etc/hosts | sed -rn '4s#^.*(644.*)( Uid.*)#\1#gp' | sed -r 's/\)//g'
644/-rw-r--r-- 

附加:sed命令总结

  • 选项
选项解释
-n 🌟取消自动打印模式空间(原数据) 一般与p一起使用
-r 🌟使用扩展正则表达式
-i修改原文件
-f从文件读取
  • 范围查询
条件解释
n按行号查找 ,第n行
n,m按行号查找 ,第n—m行
n,+m按行号查找 ,第n—n+m行
/n/按内容查找 ,包含n的行
/n/,/m /按内容查找 ,从包含n的行到包含m的行
$最后一行
  • 命令
命令解释例子
a下一行插入2a;2,5a等
i上一行插入2i;2,5i等
c当前行替换原数据2c;2,5c等
r读取文件并追加$r;2,5r等
d删除2d;2,5d等
s/原/新/g修改替换,g全局匹配s/1/one/g
p打印行2p;2,5p等
!取反sed ‘/^2/!d’ 以2开头的行不删除