Linux系统三剑客之SED

server/2024/11/27 10:21:41/

sed_0">sed的使用方法

sed文本处理:正则选定文本 -> sed进行处理

sed处理后并不会改变其内容

格式

命令行格式

sed [options] 'command' file(s)

主要参数:

  • options: -e,-n
  • command: 行定位(正则)+ sed命令(操作)

示例:

sed -n '/root/p'sed -e '10,20d' -e 's/false/true/g'

脚本格式

sed -f scriptfile file(s)

基本操作命令

注意:增删改查等操作并不会真的修改文件本身,只是对输出进行修改而已

  • p : 打印相关的行
  • a : 新增行并输出(与vim的命令类似)
  • i : 插入行(与vim的命令类似)
  • c : 代替行(与vim的命令类似)
  • d : 删除行(与vim的命令类似)
  • s : 替换(核心参数) | g : 全局

p

passwd文件进行打印

sed 'p' passwd

但是你会发现这样直接打印出的结果所有行会被输出两次

应该加上-n参数

sed -n 'p' passwd

a(后)

第5行后添加分隔符

nl passwd | sed '5a========================='

第1-4行后添加分隔符

nl passwd | sed '1,4a========================='

i(前)

第5行前添加分隔符

nl passwd | sed '5i========================='

第1-4行前添加分隔符

nl passwd | sed '1,4i========================='

c

第10行进行替换

nl passwd | sed '10c hello'

第1-10行进行替换

nl passwd | sed '1,10c hello'

结果:

hello11  games:x:12:100:games:/usr/games:/sbin/nologin12  ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin13  nobody:x:99:99:Nobody:/:/sbin/nologin14  systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin15  dbus:x:81:81:System message bus:/:/sbin/nologin16  polkitd:x:999:997:User for polkitd:/:/sbin/nologin17  abrt:x:173:173::/etc/abrt:/sbin/nologin18  tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin19  postfix:x:89:89::/var/spool/postfix:/sbin/nologin20  chrony:x:998:996::/var/lib/chrony:/sbin/nologin21  sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin22  mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash

你会发现并不是一行行的进行替换,而是整体的替换为一个

d

删除第10行

nl passwd | sed '10d'

###s

将passwd文件每一行中的nologin替换为login

sed 's/nologin/login/' passwd

注意:不要忽略上面示例命令中的每一个/

将passwd文件中的每一个:替换为%

sed 's/:/%/' 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
adm%x:3:4:adm:/var/adm:/sbin/nologin
lp%x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync%x:5:0:sync:/sbin:/bin/sync
shutdown%x:6:0:shutdown:/sbin:/sbin/shutdown
halt%x:7:0:halt:/sbin:/sbin/halt
mail%x:8:12:mail:/var/spool/mail:/sbin/nologin
operator%x:11:0:operator:/root:/sbin/nologin
games%x:12:100:games:/usr/games:/sbin/nologin
ftp%x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody%x:99:99:Nobody:/:/sbin/nologin
systemd-network%x:192:192:systemd Network Management:/:/sbin/nologin
dbus%x:81:81:System message bus:/:/sbin/nologin
polkitd%x:999:997:User for polkitd:/:/sbin/nologin
abrt%x:173:173::/etc/abrt:/sbin/nologin
tss%x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
postfix%x:89:89::/var/spool/postfix:/sbin/nologin
chrony%x:998:996::/var/lib/chrony:/sbin/nologin
sshd%x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
mysql%x:27:27:MySQL Server:/var/lib/mysql:/bin/bash 

每一行只替换了开头第一个冒号,这并不是我们想要得到的最后结果
怎么解决?
需要进行全局的替换操作

sed 's/:/%/g' 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
adm%x%3%4%adm%/var/adm%/sbin/nologin
lp%x%4%7%lp%/var/spool/lpd%/sbin/nologin
sync%x%5%0%sync%/sbin%/bin/sync
shutdown%x%6%0%shutdown%/sbin%/sbin/shutdown
halt%x%7%0%halt%/sbin%/sbin/halt
mail%x%8%12%mail%/var/spool/mail%/sbin/nologin
operator%x%11%0%operator%/root%/sbin/nologin
games%x%12%100%games%/usr/games%/sbin/nologin
ftp%x%14%50%FTP User%/var/ftp%/sbin/nologin
nobody%x%99%99%Nobody%/%/sbin/nologin
systemd-network%x%192%192%systemd Network Management%/%/sbin/nologin
dbus%x%81%81%System message bus%/%/sbin/nologin
polkitd%x%999%997%User for polkitd%/%/sbin/nologin
abrt%x%173%173%%/etc/abrt%/sbin/nologin
tss%x%59%59%Account used by the trousers package to sandbox the tcsd daemon%/dev/null%/sbin/nologin
postfix%x%89%89%%/var/spool/postfix%/sbin/nologin
chrony%x%998%996%%/var/lib/chrony%/sbin/nologin
sshd%x%74%74%Privilege-separated SSH%/var/empty/sshd%/sbin/nologin
mysql%x%27%27%MySQL Server%/var/lib/mysql%/bin/bash  

ok,这样就解决了(形式跟vim的替换神似啊朋友们🤯)

行定位

定位一行:

  • x(行号)
  • /pattern/(正则)
x(行号)

示例:

sed -n '10p' passwd

如何确认是不是第十行呢?
可以这样做:

nl passwd | sed -n '10p'
/pattern/(正则)

如何打印包含特定字符有关的行呢?
比如你想在passwd文件中找到有root的行

sed -n '/root/p' passwd

定位n行:

  • x,y(行号)
  • /pattern/,/root/
  • x,y!(取反)
  • first~step(first表示从第几行开始,step表示间隔几行输出)
x,y(行号)

假如你想打印第10-20行

nl passwd | sed -n '10,20p'

结果如下:

10  operator:x:11:0:operator:/root:/sbin/nologin
11  games:x:12:100:games:/usr/games:/sbin/nologin
12  ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
13  nobody:x:99:99:Nobody:/:/sbin/nologin
14  systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
15  dbus:x:81:81:System message bus:/:/sbin/nologin
16  polkitd:x:999:997:User for polkitd:/:/sbin/nologin
17  abrt:x:173:173::/etc/abrt:/sbin/nologin
18  tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
19  postfix:x:89:89::/var/spool/postfix:/sbin/nologin
20  chrony:x:998:996::/var/lib/chrony:/sbin/nologin   
/pattern/,/root/

如果想要通过正则表达式的方式输出第10-20行
可以这样做:

nl passwd | sed -n '/operator/,/chrony/p'

你会发现,结果跟上面的命令结果一样
OK

x,y!(取反)

其实也可以通过取反的方式输出行

比如你不想输出第十行
可以这样写:

nl passwd | sed -n '10!p'

或者说你不想输出第10-20行
可以这样写:

nl passwd | sed -n '10,20!p'
first~step

间隔指定行数进行输出
比如从第一行开始每隔一行进行输出

nl passwd | sed -n '1~2p'

练习(1)

案例一:增加文件内容

在qq.txt文件中加入相应文本:
Port 52113
PermitRootLogin no
PermitEmptyPasswords no

sed '$a port52113 \npermitrootlogin no' qq.txt

假如说加入的这两行没有跟文本对齐
可以这样做:

sed '$a \    port52113 \n    permitrootlogin no' qq.txt

这样就在两行的前面各加上了四个空格
其中$a后面的\是转义字符,是为了与语句的空格区别开,\n表示换行

案例二:文本处理

删除文本中的空行

在qq.txt文件中随便加上几个空行,保存退出

sed '/^$/d' qq.txt

案例三:服务器日志处理

cat /var/log/yum.log

找出install信息

sed -n '/install/p' /var/log/yum.log

案例四:数据筛选

获取网卡的ip信息

首先看一下网卡的信息

ifconfig

结果为:

ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500inet 192.168.43.254  netmask 255.255.255.0  broadcast 192.168.43.255inet6 2409:8910:608:bee0:43c2:af5d:e823:ff1b  prefixlen 64  scopeid 0x0<global>inet6 fe80::d127:5715:bfe1:fad8  prefixlen 64  scopeid 0x20<link>ether 00:0c:29:d2:af:1d  txqueuelen 1000  (Ethernet)RX packets 564525  bytes 625035188 (596.0 MiB)RX errors 0  dropped 0  overruns 0  frame 0TX packets 280887  bytes 24583679 (23.4 MiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536inet 127.0.0.1  netmask 255.0.0.0inet6 ::1  prefixlen 128  scopeid 0x10<host>loop  txqueuelen 1  (Local Loopback)RX packets 44  bytes 3964 (3.8 KiB)RX errors 0  dropped 0  overruns 0  frame 0TX packets 44  bytes 3964 (3.8 KiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0  

然后利用替换把不需要的部分替换为空

ifconfig ens33 | sed -n '/inet /p' | sed 's/inet //' | sed 's/ net.*//'

高级操作命令

  • {} : 允许同时使用多个sed命令,用;分隔
  • n : 读取下一个输入行(用下一个命令处理)
  • & : 具体作用看示例
  • () : 与替换操作结合使用效果更佳呦
  • r : 复制指定文件插入到匹配行
  • w : 复制匹配行拷贝指定文件里
  • q : 退出sed

{}

将第10-20行删除并且把所有nologin替换为login

nl passwd | sed '{10,20d;s/nologin/login/g}'

n

其实n的用处跟first~step类似,只不过比它高级(装逼)😏

示例:

输出偶数行:

nl passwd | sed -n '{n;p}'
nl passwd | sed -n '2~2p'

输出奇数行:

nl passwd | sed -n '{p;n}'
nl passwd | sed -n '1~2p'

按照1,4,7,10进行输出

nl passwd | sed -n '{p;n;n}'
nl passwd | sed -n '1~3p'

按照3,6,9,12进行输出

nl passwd | sed -n 'n;n;p'
nl passwd | sed -n '3~3p'

按照2,5,8,11进行输出

nl passwd | sed -n 'n;p;n'
nl passwd | sed -n '2~3p'

&

将passwd文件中的用户名称后面加上一些空格

nl passwd | sed 's/[a-zA-Z_-]\+/&      /'

结果为:

1  root      :x:0:0:root:/root:/bin/bash2  bin      :x:1:1:bin:/bin:/sbin/nologin3  daemon      :x:2:2:daemon:/sbin:/sbin/nologin4  adm      :x:3:4:adm:/var/adm:/sbin/nologin5  lp      :x:4:7:lp:/var/spool/lpd:/sbin/nologin6  sync      :x:5:0:sync:/sbin:/bin/sync7  shutdown      :x:6:0:shutdown:/sbin:/sbin/shutdown8  halt      :x:7:0:halt:/sbin:/sbin/halt9  mail      :x:8:12:mail:/var/spool/mail:/sbin/nologin10  operator      :x:11:0:operator:/root:/sbin/nologin11  games      :x:12:100:games:/usr/games:/sbin/nologin12  ftp      :x:14:50:FTP User:/var/ftp:/sbin/nologin13  nobody      :x:99:99:Nobody:/:/sbin/nologin14  systemd-network      :x:192:192:systemd Network Management:/:/sbin/nologin15  dbus      :x:81:81:System message bus:/:/sbin/nologin16  polkitd      :x:999:997:User for polkitd:/:/sbin/nologin17  abrt      :x:173:173::/etc/abrt:/sbin/nologin18  tss      :x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin19  postfix      :x:89:89::/var/spool/postfix:/sbin/nologin20  chrony      :x:998:996::/var/lib/chrony:/sbin/nologin21  sshd      :x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin22  mysql      :x:27:27:MySQL Server:/var/lib/mysql:/bin/bash

案例一:大小写转换

将用户名的首字母转换为大写/小写

知识点
元字符\u\I\U\L : 转换为大写/小写

nl passwd | sed 's/[a-z_-]\+/\u&/' passwd

案例二:大小写转换

将文件夹下的.txt文件名转换为大写

首先看一下我的当前目录下有什么.txt文件

ls *.txt

结果为:

qq.txt  test.txt

那么接下来进行操作吧

ls *.txt | sed 's/\w\+/\U&/'

结果为:

QQ.txt
TEST.txt

也许你会奇怪为什么后面的txt没有被大写
其实是因为\w并不包括.,所以后面的内容便不再进行替换

()

与练习(1)中的案例四一样,获取网卡的ip
只不过方式有一些不同
究竟不同在哪里
请看例子(其实是我也迷迷糊糊,说不明白)…

ifconfig ens33 | sed -n '/inet /p' | sed 's/inet \([0-9.]\+\).*$/\1/'

大概来说一下吧,我的理解是被()括起来的部分会被保留,其余的会被替换为空白
此处只有一对(),所以后面要替换的位置只有一个\1
假如命令中有两处被括号括起来,也就是说
有两个地方想要被保留下来,那么后面要替换的位置就要这样写\1\2
究竟如何,我也不知道,先这样吧。

看一个案例吧…

案例:获取passwd文件信息

获取用户的名字,id,和组id

sed 's/^\([a-z_-]\+\):x:\([0-9]\+\):\([0-9]\+\).*$/USER:\1 \t ID:\2 \t  UID:\3/' passwd

r

在开始解析r的使用方法之前,首先创建两个文件

echo -e '3253152514\n12425352\n124135532355' > 123.txt
echo -e 'sdafaefasf\nfsafsffef\nsffdaawwa' > abc.txt

目标:将123.txt中的内容放入到abc.txt的内容的第一行后进行输出(不会改变原文件的内容)

sed '1r 123.txt' abc.txt

w

目标1:将abc.txt中的第一行文件改写到123.txt文件中

sed '1w 123.txt' abc.txt 

目标2:将abc.txt中的全部内容文件改写到123.txt文件中

sed 'w 123.txt' abc.txt 

你有没有发现w的写入操作是将被改写的文件内容全部覆盖?

q

目标:passwd文件中找到第一个nologin就停止输出

nl passwd | sed '/nologin/q'

http://www.ppmy.cn/server/145312.html

相关文章

C++11特性(详解)

目录 1.C11简介 2.列表初始化 3.声明 1.auto 2.decltype 3.nullptr 4.范围for循环 5.智能指针 6.STL的一些变化 7.右值引用和移动语义 1.左值引用和右值引用 2.左值引用和右值引用的比较 3.右值引用的使用场景和意义 4.右值引用引用左值及其一些更深入的使用场景分…

老旧前端项目如何升级工程化的项目

因为历史的原因存在着大量的老旧前端项目&#xff0c;而在今天的开发环境中已经不再适应了&#xff0c;于是产生了升级到新的环境的需求。比如笔者当前的一个登录页面项目&#xff0c;就是以下面为技术栈的老旧项目。 基于 jQuery包管理基于 require.js&#xff0c;甚至有的没…

Error: Invalid version flag: if 问题排查

问题描述&#xff1a; 国产化系统适配&#xff0c;arm架构的centos 在上面运行docker 启动后需要安装数据库 依赖perl 在yum install -y perl 时提示&#xff1a; “Error: Invalid version flag: if”

MYSQL表的增删改查(下)

目录 修改&#xff08;Update&#xff09; 删除&#xff08;Delete&#xff09; 本文主要介绍的是表的修改的删除&#xff0c;如果需要了解新增和查询的可以看&#xff1a;MYSQL 表的增删改查&#xff08;上&#xff09;-CSDN博客 修改&#xff08;Update&#xff09; 语法…

环状DNA序列的最小表示法

问题描述 环状 DNA 又称超螺旋&#xff0c;即一段碱基序列呈现环状&#xff0c;在分析时&#xff0c;需要将相同序列的环状 DNA 分到相同组内&#xff0c;现需将环状碱基序列按照最小表示法进行排序。 一段长度为 n 的碱基序列&#xff0c;按照顺时针方向&#xff0c;碱基序列…

代码随想录算法训练营第十三天(递归遍历;迭代遍历;统一迭代;层序遍历)

递归遍历 LeetCode 144. 二叉树的前序遍历 题目链接&#xff1a;二叉树的前序遍历题目链接 代码 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) …

基于Java Springboot餐饮美食分享平台

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA 数据库&#xff1a;MySQL8.0 …

Django 路由层

1. 路由基础概念 URLconf (URL 配置)&#xff1a;Django 的路由系统是基于 urls.py 文件定义的。路径匹配&#xff1a;通过模式匹配 URL&#xff0c;并将请求传递给对应的视图处理函数。命名路由&#xff1a;每个路由可以定义一个名称&#xff0c;用于反向解析。 2. 基本路由配…