一、sed简介
1、什么是sed
Sed是一个强大的文本处理工具,其名称是Stream Editor(流编辑器)的缩写。它被设计用于根据用户定义的规则对文本进行逐行处理和转换。
Sed通过从输入流中逐行读取文本,并根据用户指定的命令来对每一行进行处理
2、sed原理
sed的工作原理是逐行读取输入文本,并根据用户指定的命令对每一行进行处理,通过模式匹配和命令执行来实现文本的处理和转换。
Input Text Pattern Space Output Text
------------ -------------- -------------
| Line 1 | -----> | Pattern | -----> | |
| Line 2 | | Space | | Modified |
| Line 3 | | | | Text |
| ... | | | | |
------------ -------------- -------------
“Input Text” 是输入的文本,由多行组成,每一行都会依次进入 “Pattern Space”;
“Pattern Space”是 sed 使用的缓冲区。
sed 会根据用户指定的模式(例如,文本匹配规则)进行模式匹配,然后执行相关的命令来处理当前的行。
命令执行完成后,如果有修改操作,那么 “Modified Text” 将会保存修改后的文本,最后输出作为 Sed 的结果。
3、sed核心功能
sed的核心功能:增删改查(可配合正则表达式)
查: p
删: d
改: s(字符串替换)、c(整行替换)、y(对应字符进行替换,效果类似tr命令)
增: i(在行前插入内容)、a(在行后添加内容)、r(在行后读入文件的内容)
复制粘贴:H(复制)、d(删除)、G(粘贴到指定行下方)
二、sed命令格式详解
1、命令格式
sed [option]... 'script;script;...' [input file...]
选项 自身脚本语法 支持标准输入管道
2、常用选项
选项 | 功能 |
---|---|
-n | 不输出模式空间内容到屏幕,即不自动打印 |
-e | 进行多点编辑 |
-f | 从指定文件中读取编辑脚本 |
-r,-E | 使用扩展正则表达式 |
-i | 直接在源文件中修改 |
-i.bak | 备份文件并原处编辑 |
-s | 将多个文件视为独立文件,而不是单个连续的长文件流 |
2.1、打印输出
[root@localhost ~]#sed ' '
####默认将输入内容打印出来,系统自带自动打印
[root@localhost ~]# cat -n /etc/passwd > /data/passwd
[root@localhost ~]# sed '' /data/passwd
#查看文件内容,后面跟文件,显示文件,与cat命令相似
[root@localhost data]#seq 10 |sed -n '1~2!p'
#取反
[root@localhost data]#seq 10 |sed '3q'
#打印3个数就结束或退出
2.2、sed脚本格式
注意:通常-n和’p’一起使用
'地址+命令'组成
多个命令 {命令1;命令2} 用花括号括起来
[root@localhost ~]# sed -n '1p;3p;5p' /etc/passwd
#打印1,3,5行
2.2.1、不加地址,对全文进行处理(比如行号)
[root@localhost ~]#sed ' ' /etc/passwd
2.2.2、单地址
#:指定的行,$:最后一行
[root@localhost ~]# ifconfig ens33|sed -n '2p'
#打印第2行
[root@localhost ~]# sed -n '$p' /etc/passwd
#打印最后一行
/pattern/:被此处模式所能够匹配到的每一行,正则表达式
[root@localhost ~]# sed -n '/^root/p' /etc/passwd
#打印以root开头的行
2.3、地址范围
#,# //从#行到第#行,3,6 从第3行到第6行
#,+# //从#行到+#行,3,+4 表示从3行到第7行
/pat1/,/pat2/ //第一个正则表达式和第二个正则表达式之间的行
#,/pat/ //从#号行为开始找到 pat为止
/pat/,# //找到#号个pat为止
[root@localhost ~]# ifconfig ens33|sed -n '1,3p'
#从第1行打印到第3行
[root@localhost ~]#ifconfig ens33|sed -n '3,+2p'
#从第3行打印到第5行
[root@localhost ~]#sed -n '/^b/,/^f/p' /etc/passwd
#从以b开头到以f开头的行
[root@localhost ~]#sed -n '3,/^g/p' /etc/passwd
#从第3行到以g开头结尾
2.4、步进 ~
1~2 奇数行
2~2 偶数行
[root@localhost ~]#seq 10 |sed -n '1~2p'
[root@localhost ~]#seq 10 |sed '2~2d'
#打印奇数行
[root@localhost ~]#seq 10 |sed -n '2~2p'
[root@localhost ~]#seq 10 |sed '1~2d'
#打印偶数行
2.5、修改内容
[root@localhost ~]#sed -i '3ahehehe' test.txt
#永久修改
[root@localhost ~]#sed -i '5d' test.txt
#永久删除第5行
如果想要真的替换,需要用-i选项,建议用-i之前对原文件进行备份
[root@localhost data]#cp /etc/sysconfig/network-scripts/ifcfg-ens33 .
[root@localhost data]#sed -i.bak '8aIPADDR=8.8.8.8' ifcfg-ens33
2.6、多点编辑
sed支持一个或多个-e参数
[root@localhost ~]# sed -n -e '1p' -e '3p' /data/wyx
#打印第一行和第3行
[root@server ~]# sed -ne '1p' -ne '5p' /etc/passwd
3、常用命令动作
选项 | 功能 |
---|---|
p | 打印输出 |
d | 删除指定行 |
i | 在指定行之前插入内容 |
a | 在指定行后面插入内容 |
c | 替换指定行所有内容 |
s | 搜索替换 |
3.1、删除
[root@localhost ~]#seq 10 |sed '2d'
#把第二行删掉
[root@localhost ~]#seq 10 |sed '1,5d'
#删除1到5行
[root@localhost ~]#sed '/^r/d' /data/passwd
#删除以r开头的行
[root@localhost ~]# sed '/^b/d;/^d/d' /data/passwd
#删除以b和d开头的行
3.2、搜索替换
替换某个关键词的话需要使用s指令
sed 选项 's/搜索的内容/替换的内容/动作'
其他形式:s@@@,s###
[root@localhost ~]# sed 's/root/ROOT/' /data/passwd
#搜索root所在行把第一个出现的root换成ROOT
[root@localhost ~]# sed -n 's/root/ROOT/gp' /data/passwd
#搜索root所在行,把所有出现的root都替换成ROOT
[root@localhost ~]# sed -n 's/o/O/2p' /data/passwd
#搜索字母o,仅替换每行第二个o为大写O
[root@localhost ~]# sed -n 's/root//gp' /data/passwd
#将root替换为空
[root@localhost ~]# sed -n '1,5s/^/#/gp' /data/passwd
#把1-5行的开头都插入#号
[root@localhost ~]# sed -n 's/\/sbin\/nologin/kgc/gp' /data/passwd
#把所有/sbin/nologin换成kgc,/需要转义
[root@localhost ~]#sed -i 's/r..t/&er/g' /data/passwd
#&指代之前找到的内容
#在"/data/passwd"文件中,将以"r"开头和"t"结尾的两个字符之间的字符(不包括开头和结尾)替换为"er",并保存修改后的结果到原始文件
我们只想搜索以sync开头的行并且前面加#号,那就需要保留sync,那就要把搜索的字符写成&就会被保留不会一起替换,观察不加&的区别
[root@localhost ~]# sed -n 's/^sync/#&/gp' /data/passwd
#在文件"/etc/passwd"中找到以"sync"开头的行,并将这些行替换为以"#"开头的注释行,并输出替换后的结果
3.3、替换
c指令使得整行内容全部替换
[root@localhost ~]#seq 10 > test.txt
[root@localhost ~]#sed '3chehehe' test.txt
#把3替换成hehehe
[root@localhost ~]#sed '3chehehe \nhaha\nlala' test.txt
#\n多行追加
3.4、插入文件
[root@localhost data]#seq 10 |sed '2r /data/wyx'
#把/data/wyx文件插到第2行后面
[root@localhost ~]# sed '3r /etc/hosts' /data/wyx
#将/etc/hosts文件插入到第三行后面
[root@localhost ~]# sed '/2/r /etc/hosts' /data/passwd
#在文件"/data/passwd"中查找包含数字"2"的行,并将"/etc/hosts"文件的内容插入到该行之后
[root@localhost ~]# sed '$r /etc/hosts' /data/passwd
#将在文件 “/data/passwd” 的最后一行之后追加 “/etc/hosts” 文件的内容
[root@localhost ~]#seq 10 > test.txt
[root@localhost ~]#sed '3ahehehe' test.txt
#在3后面加hehehe
[root@localhost ~]#sed '3ihehehe' test.txt
#在3前面加hehehe
[root@localhost data]#![seq 10 |sed -n '0~2wa.txt'
#把偶数行写进a.txt
[root@localhost ~]# sed '2ihello world' /data/passwd
#在文件"/data/passwd"中的第2行之前插入"hello world"
[root@localhost ~]# sed '3ihello\nworld' /data/passwd
#在文件"/data/passwd"中的第3行之前插入"hello"和"world"两个单词,并在它们之间换行
[root@localhost ~]# sed '/\/bin\/bash/a hello world' /data/passwd
#在文件"/data/passwd"中每一行匹配"/bin/bash"的行之后追加"hello world"
[root@localhost ~]#sed '/shengjie/a hello world;3p;3i shell' /data/passwd
#在文件"/data/passwd"中,在包含"shengjie"的行之后添加"hello world",然后在第3行处打印出该行内容,并在第3行之前插入"shell"
4、分组后项引用
echo 123abcxyz |sed -nr 's/(123)(abc)(xyz)/\1/p'
##分组 s//代表查找替换 ()代表分组 \1 代表第一个组
echo 123abcxyz |sed -nr 's/123(abc)(xyz)/\1/p'
echo 123abcxyz |sed -nr 's/123abc(xyz)/\1/p'
ifconfig ens33|sed -nr 's/.*inet (.*) netmask.*/\1/p'
#分组提取ip地址
echo "/etc/sysconfig/network-scripts/ifcfg-ens33" |sed -nr 's@(.*/)(.*)@\2@p'
#提取ifcfg-ens33
[root@localhost data]#stat /tmp
#提取1777
[root@localhost data]#stat /tmp|sed -nr '4p'
[root@localhost data]#stat /tmp|sed -nr '4s/.*([0-9]{4}).*/\1/p'
5、变量
[root@localhost data]#vim test
haha
root
hehe
lala
[root@localhost data]#name=root
[root@localhost data]#sed -i 's/$name/wyx' test
#把root修改成wyx
[root@localhost data]#cat test
#没修改成功
[root@localhost data]#sed -i 's/'$name'/wyx' test
[root@localhost data]#cat test
#修改成功
6、修改网卡名称
[root@localhost data]#vim /etc/default/grub
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
#GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet net.ifnames=0"
#修改这行
[root@localhost data]#grub2-mkconfig -o /boot/grub2/grub.cfg
cd /etc/sysconfig/network-scripts
mv ifcfg-ens33 ifcfg-eth0
vim eth0
systemctl restart network