sed 命令

sed 详解

        sed 即 Stream EDitor,和 vi 不同,sed是行编辑器

        Sed是从文件或管道中读取一行,处理一行,输出一行;再读取一行,再处理一行,再输出一行,直到最后一行。每当处理一行时,把当前处理的行存储在临时缓冲区中,称为模式空间(PatternSpace),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。一次处理一行的设计模式使得sed性能很高,sed在读取大文件时不会出现卡顿的现象。如果使用vi命令打开几十M上百M的文件,明显会出现有卡顿的现象,这是因为vi命令打开文件是一次性将文件加载到内存,然后再打开。Sed就避免了这种情况,一行一行的处理,打开速度非常快,执行速度也很快

一、基本用法

格式:

sed    [option]...    'script;script;...'        [input   file...]
           选项          自身脚本语法          支持标准输入管道

语法:
地址 + 语法命令

常用选项:

-n 不输出模式空间内容到屏幕,即不自动打印

-e

多点编辑[root@www data]#sed -n -e '/^r/p'  -e'/^b/p' /etc/passwd
-f FILE 从指定文件中读取编辑脚本
-r ,-E 使用扩展正则表达式
-i.bak 备份文件并原处编辑

#说明: 
-ir   不支持
-i -r   支持
-ri     支持
-ni     会清空文件

1.1 用法:

[root@localhost ~]#sed 
#提示错误
[root@localhost ~]#sed ' '
####默认将输入内容打印出来,系统自带自动打印
aaa
aaa
dd
dd
#输入aaa回车后会自动打印一行aaa


[root@localhost ~]#sed '' /etc/fstab 
####查看文件内容


[root@localhost ~]#sed '' 

1.2 sed 脚本格式 '脚本语法'

脚本格式如下:

1. 不给地址:对全文进行处理(比如行号)
2. 单地址:
   #:指定的行,$:最后一行
   /pattern/:被此处模式所能够匹配到的每一行,正则表达式
3. 地址范围:
   #,#     #从#行到第#行,3,6 从第3行到第6行
   #,+#   #从#行到+#行,3,+4 表示从3行到第7行
   /pat1/,/pat2/    第一个正则表达式和第二个正则表达式之间的行
   #,/pat/  从#号行为开始找到 pat为止 
   /pat/,#  找到#号个pat为止
4. 步进:~
     1~2 奇数行
[root@localhost data]#seq 10 | sed -n '1~2p'

     2~2 偶数行
[root@localhost data]#seq 10 | sed -n '2~2p'

sed -n 'n;p' testfile1		#打印偶数行

sed -n '2,${n;p}' testfile1   #以2为起始(不输出2),输出3 ,每输出一个数 下一个数不输出  输出下下个数以此类推。




命令
p     打印当前模式空间内容,追加到默认输出之后
Ip    忽略大小写输出
d     删除模式空间匹配的行,并立即启用下一轮循环
a [\]text 在指定行后面追加文本,支持使用\n实现多行追加
i [\]text 在行前面插入文本
c [\]text 替换行为单行或多行文本
w file    保存模式匹配的行至指定文件   seq 10 |sed -n '2wa.txt'
r file    读取指定文件的文本至模式空间中匹配到的行后    seq 10|sed '2r /etc/issue'
=   为模式空间中的行打印行号   sed '2=' /etc/passwd      sed -n -e '=;p' /etc/passwd
!   模式空间中匹配行取反处理seq 10 |sed -n '1~2!p'
q           结束或退出sed     seq 10 | sed '3q'

seq的一些‘脚本语法’用法:

[root@localhost profile.d]#seq 3|sed 'p'
#带有自动打印功能,p又再打印一遍
1
1
2
2
3
3

[root@localhost profile.d]#seq 3|sed -n 'p'
#-n 选项关闭自动打印功能
1
2
3


#脚本语法里 加入地址

[root@localhost ~]#seq 10 | sed -n '3p'
#直接显示第3行
3

[root@localhost profile.d]#ifconfig ens33|sed -n '2p'
#直接显示第二行内容
        inet 192.168.80.7  netmask 255.255.255.0  broadcast 192.168.80.255


[root@localhost ~]#seq 10 |sed -n '$p'
#显示最后一行
10



####如何显示范围  行号,行号
[root@localhost ~]#seq 10|sed -n '3,6p'
###显示范围
3
4
5
6
[root@localhost ~]#seq 10|sed -n '3,+4p'
##3 往后加4行
3
4
5
6
7

sed 支持正则表达式:

###还支持正则表达式

[root@localhost ~]#sed '/root/p' /etc/passwd
###自动打印需要关闭否则会全部打印
root:x:0:0:root:/root:/bin/bash
省略多行。。。。。。。。
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin


[root@localhost ~]#sed -n '/root/p' /etc/passwd
##将包含root的行打印出来   /root(需要匹配的内容)/p(打印)  文件名  
###与 grep root /etc/passwd 功能相同
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin


[root@localhost profile.d]#sed -n '/^a/p' /etc/passwd
#将以a开头的行打印出来      /^a/p(打印)   文件名
###与 grep ^a /etc/passwd 功能相同
adm:x:3:4:adm:/var/adm:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin




###还可以匹配 两个正则表达式之间的行

[root@localhost ~]#cat /etc/passwd
###我想显示 b 开头 和 s 开头中间的行


[root@localhost profile.d]#sed -n '/^b/,/^s/p' /etc/passwd
###     基本格式     '/表达式1/,/表达式2/p' (不要忘记打印)p  文件名
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

匹配两个正则表达式之间的行的匹配方式:(如果有多个复合条件的表达式)
先开始找 b 开头一直找到 s 开头
找到后再重新找 b 开头,一找到 s 开头,有就显示,没有就显示找到的内容
重复循环
如果没有找到 s 开头的行,那么就是 b 开头行 显示到末尾。
如果没有找到 b 开头就不显示。


比如:
[root@localhost profile.d]#sed -n '/^d/,/^a/p' /etc/passwd
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin




######面试题,显示几点到几点分的日志#######
让你查找几点几分到几点几分之间的日志

[root@localhost ~]#sed -n '/2023:11:56:41/,/2023:11:56:44/p' access_log
#匹配含有 2018:11:56:41 至 含有 2018:11:56:44 的行(后面要加文件名)

命令 d

删除模式空间匹配的行,并立即启用下一轮循环

[root@localhost data]#seq 5 | sed  '3d'
###将第三行删除
1
2
4
5

##修改文件内容,常常用于修改配置文件
-i           与         -i.bak
修改文件  修改文件前先备份

[root@localhost ~]#seq 10 >test.txt
[root@localhost ~]#cat test.txt 
1
2
3
4
5
6
7
8
9
10
[root@localhost ~]#sed -i '2~2d' test.txt   #把文件内偶数行删除
[root@localhost ~]#cat test.txt
1
3
5
7
9



#####    -a 追加
[root@localhost ~]#seq 5 |sed '2ahehe'
###第二行后追加hehe (改变显示)
1
2
hehe
3
4
5



[root@localhost data]#cat host.txt 
wang
li
ming
[root@localhost data]#sed -i '2a\lisi' host.txt    #在第二行后追加lisi
#修改文件内部需要多加一个\
[root@localhost data]#cat host.txt 
wang
li
lisi
ming


[root@localhost data]#sed -i '3a\zhangsan\nxuqing' host.txt  #在第三行后追加zhangsan,并\n
换行添加xuqing
###\表示空格    \n 表示换行
[root@localhost data]#cat host.txt 
wang
li
lisi
zhangsan
xuqing
ming



#####    -i 前面行插入
[root@localhost ~]#seq 5 |sed '2ihehe'
#第二行前面插入hehe
1
hehe
2
3
4
5


#####    -c 替换
[root@localhost ~]#seq 5 |sed '2chehe'
#第二行替换成hehe
1
hehe
3
4
5

#####    -! 取反
[root@localhost ky15]# seq 5 |sed -n '2!p'
#取反  原意是只显示第2行,加了!是除了第二行其它都显示。
1
3
4
5


#####    -r  追加文本
[root@localhost data]#cat /etc/issue
\S
Kernel \r on an \m

[root@localhost data]#seq 5 |sed '2r /etc/issue'
#在第二行后追加/etc/issue内的内容。
1
2
\S
Kernel \r on an \m

3
4
5



#####     -w  保存模式匹配的行至指定文件
[root@localhost data]#seq 10 |sed -n '2wa.txt'
#将第二行的内容覆盖到a.txt文件中。(保存其它内容会覆盖原本内容)
[root@localhost data]#cat a.txt
2

[root@localhost data]#seq 10 |sed -n '3wa.txt'
[root@localhost data]#cat a.txt
3
#可以看到原来的已被覆盖。


#####     -=  打印行号(但是换行打印)
[root@localhost data]#sed '=' host.txt 
1
wang
2
ssi
3
li
4
lisi
5
zhangsan
#在每一行的前面(上一行)打印行号
[root@localhost data]#sed '2=' host.txt      #打印第二行的行号。 
wang
2
ssi
li
lisi
zhangsan

1.3 搜索替代

s/pattern/string/修饰符   查找替换,支持使用其它分隔符,可以是其它形式:s@@@,s###

@和#都可为分隔符。


替换修饰符:
g    行内全局替换
p    显示替换成功的行
w   /PATH/FILE 将替换成功的行保存至文件中
I,i    忽略大小写

例子:

如何把在不打开文件的情况下把SELinux的模式改为 宽容模式

enforcing:强制模式

permissive:宽容模式

disabled:关闭

使用 sed -i 's/原内容/新内容/修饰符'   文件位置  或  sed -i.bak 's/原内容/新内容/修饰符'   文件位置
来更改文件内的内容。

selinux 文件位置 :/etc/selinux/config

[root@localhost data]#cat /etc/selinux/config

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
SELINUX=enforcing   #我们要在不打开文件的情况把它改成  SELINUX=permissive 。
# SELINUXTYPE= can take one of three two values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected. 
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted


[root@localhost data]#sed -i.bak 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config


-i.bak 为备份文件(原名.bak) ,备份的位置在 /etc/selinux/目录下的 config.bak

使用 sed 命令把文件内 root 全部替换为 admin。

[root@localhost data]#sed -i 's/root/admin/g' 1.txt
[root@localhost data]#cat 1.txt 
admin
admin
hehe
toor
admin

 关于 & 

[root@localhost ~]#sed 's/root/&er/g' /etc/passwd
#&指代之前找到的内容

#其实就是 sed 's/root/rooter/g' /etc/passwd

分组替换

[root@localhost ~]#echo 123abcxyz |sed -r 's/(123)(abc)(xyz)/\1/'
##分组 s//代表查找替换  ()代表分组    \1 代表留下的组  -r代表使用扩展正则
123

[root@localhost ~]#echo 123xyzabc |sed -r 's/(123)(xyz)(abc)/\1\2/'
123xyz
[root@localhost ~]#echo 123xyzabc |sed -r 's/(123)(xyz)(abc)/\1\3/'
123abc

使用sed 匹配出当前主机的 IP 地址。

.*	任意长度的任意字符  不包括0次     1到正无穷

[root@localhost data]#ifconfig ens33|sed -nr '2p'
        inet 192.168.80.7  netmask 255.255.255.0  broadcast 192.168.80.255



[root@localhost data]#ifconfig ens33|sed -nr '2s/.*inet (.*)  netmask.*/\1/p'
192.168.80.7

如果替换时 有 / 号改如何处理?

[root@localhost selinux]#echo /etc/sysconfig/network-scripts/ifcfg-ens33 |sed -nr 's@^(.*)/([^/]+)@\2@p'
ifcfg-ens33

[root@localhost data]#echo "/etc/sysconfig/network-scripts/ifcfg-ens33"|sed -nr 's#^.*\/(.*)#\1#p'
-nr 's@^(.*)/([^/]+)@\2@p'
ifcfg-ens33

如何使用一条sed命令 替换两个文本的内容。

[root@localhost selinux]#cat 1.txt 2.txt
123
456
123
abc
[root@localhost selinux]#sed -i -e 's/123/cba/' 1.txt  -e 's/abc/789/' 2.txt

面试题:提取版本号

[root@localhost data]#cat ban.txt
ant-1.9.7.jar
ant-launcher-1.9.7.jar
antlr-2.7.7.jar
antlr-runtime-3.4.jar
aopalliance-1.0.jar
archaius-core-0.7.6.jar
asm-5.0.4.jar
aspectjweaver-1.9.5.jar
bcpkix-jdk15on-1.64.jar
bcprov-jdk15-1.46.jar
bcprov-jdk15on-1.64.jar
checker-compat-qual-2.5.5.jar

#提取这些版本号 1.9.7

#使用 sed 命令 提取。
[root@localhost data]#cat ban.txt | sed -r 's/.*-(.*).jar/\1/'
1.9.7
1.9.7
2.7.7
3.4
1.0
0.7.6
5.0.4
1.9.5
1.64
1.46
1.64
2.5.5


#使用 awk 命令 提取
[root@localhost data]#rev ban.txt
raj.7.9.1-tna
raj.7.9.1-rehcnual-tna
raj.7.7.2-rltna
raj.4.3-emitnur-rltna
raj.0.1-ecnaillapoa
raj.6.7.0-eroc-suiahcra
raj.4.0.5-msa
raj.5.9.1-revaewjtcepsa
raj.46.1-no51kdj-xikpcb
raj.64.1-51kdj-vorpcb
raj.46.1-no51kdj-vorpcb
raj.5.5.2-lauq-tapmoc-rekcehc

[root@localhost data]#rev ban.txt |awk -F'raj.' '{print $2}'|awk -F'-' '{print $1}'|rev
1.9.7
1.9.7
2.7.7
3.4
1.0
0.7.6
5.0.4
1.9.5
1.64
1.46
1.64
2.5.5

1.4 变量

[root@www data]#name=root
[root@www data]#sed -nr '/$name/p' /etc/passwd    #单引号不识别变量。
[root@www data]#sed -nr "/$name/p" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

[root@www data]#sed -nr '/'$name'/p' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin




[root@www data]#port=8080
[root@www data]#sed -ri 's/^Listen 80/Listen '$port'/' httpd.conf



[root@www data]#sed -ri -e 's/^Listen 80/Listen '$port'/' -e "/^#ServerName/c ServerName `hostname`:$port"   httpd.conf

1.5 修改grub配置文件

在 /etc/default/grub 中 GRUB_CMDLINE_LINUX 末尾添加 net.ifnames=0 参数。

net.ifnames=0    禁用操作系统基于硬件生成网卡名称这种规则

方法1:
sed -ri.bak '/^GRUB_CMDLINE_LINUX/s#(.*)"$#\1 net.ifnames=0"#' /etc/default/grub 
// s### 中 #为分隔符。


#过滤出以GRUB_CMDLINE_LINUX开头的行,并把前面 及 末尾的 " 号替换为\1 net.ifnames=0" ,\1表示(.*)内的内容也就是GRUB_CMDLINE_LINUX="crashkernel=auto rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet



方法2:
sed -ri.bak '/^GRUB_CMDLINE_LINUX/s#"$# net.ifnames=0"#' /etc/default/grub
// s### 中 #为分隔符。

#这个方法比方法一更加简便  ,过滤出以GRUB_CMDLINE_LINUX开头的行,并把末尾的 " 号替换成 net.ifnames=0"
!!!!替换的内容前要加空格。



改完后记得重新生成grub配置文件
grub2-mkconfig -o /boot/grub2/grub.cfg

使用 sed 命令 过滤出 stat /tmp 命令结果中 的权限。

[root@localhost data]#stat /tmp
  文件:"/tmp"
  大小:4096      	块:8          IO 块:4096   目录
设备:fd00h/64768d	Inode:67145096    硬链接:13
权限:(1777/drwxrwxrwt)  Uid:(    0/    root)   Gid:(    0/    root)
环境:system_u:object_r:tmp_t:s0
最近访问:2016-11-05 23:38:36.000000000 +0800
最近更改:2024-01-30 15:08:21.943257931 +0800
最近改动:2024-01-30 15:08:21.943257931 +0800
创建时间:-


使用 sed 过滤 出 drwxrwxrwt 。

[root@localhost data]#stat /tmp|sed -nr '4s#.*/(.*)\)  Uid.*#\1#p'
drwxrwxrwt

你可能感兴趣的:(linux,运维,服务器)