sed_0">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'