1.sed基本概述
sed是一个流编辑器,能够处理特别大的文件,
能够对标准输出或文件进行逐行处理,
简单来说sed可以实现对文件内容的过滤、替换、增、删、改、查。
2.sed的工作模式
sed读取一行,存放在缓存区,然后处理,最后输出。
它是一行一行载入内存的,不像vim一次将文件全都载入内存,内存不足的情况下直接卡死。
所以编辑大文件sed更合适。
3.sed基础语法
形式一:stdout | sed [选项] "匹配方式 命令"
形式二:sed [选项] "匹配方式 命令" file
sed学习步骤:
option 选项
pattern 匹配方式
command 命令
例:变更selinux配置文件的内容(变更文件内容的方式)
sed -i '/^SELINUX=/c SELINUX=enforcing' /etc/selinux/config
匹配/etc/selinux/config文件中以SELINUX=开头的行,替换为SELINUX=enforcing
-i 选项
// pattern匹配
c command动作 c表示替换
sed option 选项
选项 | 含义 |
---|---|
-n | 只打印匹配的行(取消文件的默认输出,只打印过滤的那行) |
-e | 允许编辑多项 |
-f | 把pattrn保存在文件,指定文件才执行 |
-r | 支持扩展正则表达式 |
-i | 直接变更文件内容 |
sed 选项示例
示例文件:
cat file.txt
I love shell
I love SHELL
This is test file
sed -n选项示例
取消默认输出
sed -n '/shell/p' file.txt
sed -e选项示例
编辑多项
sed -n -e '/shell/p' -e '/SHELL/p' file.txt
sed -f选项示例
把pattern写在文件中,-f指定文件,调用文件中的匹配
sed -n -f sed.txt file.txt
sed -r选项示例
支持扩展正则表达式
sed -nr '/shell|SHELL/p' file.txt
sed pattern 匹配
命令格式:sed [option] '/pattern/command' file
sed 匹配示例
打印/etc/passwd文件中的第10行
sed -n '10p' /etc/passwd
打印/etc/passwd文件中的第10行到第15行结束
sed -n '10,15p' /etc/passwd
打印/etc/passwd文件中的第10行开始到后面5行结束
sed -n '10,+5p' /etc/passwd
打印/etc/passwd中开头匹配bin字符串的内容
sed -n '/^bin/p' /etc/passwd
打印/etc/passwd中开头为root的行开始,到开头为ftp的行结束的内容
sed -n '/^root/,/ftp/p' /etc/passwd
打印/etc/passwd中第10行开始,到含有ftp的内容的行结束的内容
sed -n '10,/ftp/p' /etc/passwd
打印/etc/passwd中第8行开始,到含有/sbin/nologin的内容的行结束内容,这里/需要转义一下
sed -n '8,/\/sbin\/nologin$/p' /etc/passwd
sed command 命令
追加
删除
替换
追加
命令 | 含义 |
---|---|
a | 行后追加内容 |
i | 行前追加内容 |
r | 读入外部文件,行后追加 |
w | 将匹配行写入外部文件 |
例:修改ssh配置文件,在第16行后追加下列三行内容,\n换行
Port 666
AddressFamily any
UseDNS no
#举例说明使用场景
sed -i '16a Port 666\nAddressFamily any\nUseDNS no' /etc/ssh/sshd_config
追加示例
a 行后追加内容
匹配/bin/bash的行,在其行后追加一行内容
sed -i '/\/bin\/bash/a sed test' passwd
i 行前添加内容
以/bin开头的行到以sshd开头的行,前面添加一行
sed '/^bin/,/^sshd/i sed TEST' passwd
i 行前添加内容
指定给文件的第30行添加一行内容
sed '30i this is a test' passwd
如果要修改文件内容的话,前面再加上-i选项
r 读取外部文件 行后追加
将sed.txt中的内容,追加到匹配的行后面
sed '/^wang/r sed.txt' passwd
w 将匹配行写入外部文件
匹配/bin/bash所有的行,将其保存至当前路径下的login.txt文件中
sed '/\/bin\/bash/w ./login.txt' passwd
替换示例
修改passwd文件第一行第一个root为ROOT
sed '1s/root/ROOT/' passwd
加g代表替换这行所有的匹配内容,不加就只替换第一个
sed '1s/root/ROOT/g' passwd
修改passwd文件第1行到第10行中所有的/sbin/nologin为/bin/bash
sed '1,10s/\/sbin\/nologin/\/bin\/bash/' passwd
当遇到需要转义的时候会看起来很乱
可以用#
或者@
代替/
符号之间相互替换,更方便查看
效果一样
sed '1,10s#/sbin/nologin#/bin/bash#' passwd
sed '1,10s@/sbin/nologin@/bin/bash@' passwd
修改passwd文件中匹配到/sbin/nologin的行,将匹配到行中的login为该大写的LOGIN
sed '/\/sbin\/nologin/s#login#LOGIN#g' passwd
修改passwd文件中从匹配到以root开头的行,到匹配到行中包含bin的所有行,将bin改为BIN
sed '/^root/,/bin/s/bin/BIN/g ' passwd
5.修改SELINUX=enforcing修改为SELINUX=disabled (可以使用c替换方式)
sed ‘/^SELINUX=/s/enforcing/disabled/g’ selinux
sed ‘/^SELINUX=/c SELINUX=disabled’ selinux
将nginx.conf配置文件添加注释
sed 's/^/#/' nginx.conf
使用sed提取ens192网卡的IP地址
ifconfig ens192|sed -rn '2s/^.*et //p'|sed -rn 's/ ne.*//p'
ifconfig ens192|sed -rn '2s/(^.*et) (.*) (net.*)/\2/p'
删除示例
命令 | 含义 |
---|---|
1d | 删除第1行的内容 |
1,5d | 删除1行到5行的内容 |
2,+5d | 删除2行以及往下的5行的内容 |
/pattern1/d | 删除每行中匹配到pattern1的行内容 |
/pattern1/,/pattern2/d | 删除匹配到pattern1的行直到匹配到pattern2的所有行内容 |
/pattern1/,10d | 删除匹配到pattern1的行到10行的所有行内容 |
10,/pattern1/d | 删除第10行直到匹配到pattern1的所有内容 |
删除/etc/passwd中的第15行
sed '15d' passwd
删除/etc/passwd中的第8行到第14行的所有内容
sed '8,14d' passwd
删除/etc/passwd中以/sbin/nologin结尾的行
sed '/\/sbin\/nologin$/d' passwd
删除/etc/passwd中以bin开头的行,到以ntp开头的行的所有内容
sed '/^bin/,/^ntp/d' passwd
删除/etc/passwd中第3行到以ftp开头的所有行内容
sed '3,/^ftp/d' passwd
典型需求:删除Nginx配置文件中所有的注释以及空行
sed -ri '/^#|^$/d' nginx.conf
sed相关脚本
处理一个ansible的invtory主机清单。
1.输出主机组,一对 [ ] 为一个主机组。
2.输出每个主机组下的主机总个数。
3.输出主机组下,每台主机的地址。
示例文件:
[webservers]
192.168.10.10
192.168.10.11
192.168.10.12
192.168.10.13
192.168.10.14
[proxy]
192.168.10.15
192.168.10.16
192.168.10.17
192.168.10.18
192.168.10.19
1.想办法输出主机组名称
打印以[
开头的行,然后去掉[ ]就是我们要的主机名
sed -n '/^\[/p' hosts |sed -r 's#\[|\]##g'
2.输出每个主机组下的主机总个数
sed -n '/\[webservers\]/,/^\[/p' hosts | sed -r '/\[|^$/d'|wc -l
sed -n '/\[proxy\]/,/^\[/p' hosts | sed -r '/\[|^$/d'|wc -l
这里可以用传参的方式代替主机组名
sed -rn '/\['$1'\]/,/^\[/p' hosts | sed -r '/^\[|^$/d' | wc -l
在调用函数的时候传参
脚本:
#!/bin/bash
get_groupname (){
sed -n '/^\[/p' hosts | sed -r 's#\[|\]##g'
}
get_hostnum () {
sed -rn '/\['$1'\]/,/^\[/p' hosts | sed -r '/^\[|^$/d' | wc -l
}
for host in $(get_groupname)
do
echo "主机组名: $host ,$host 中包含 $(get_hostnum $host) 台主机"
done
脚本执行效果:
3.输出主机组下,每台主机的地址。
sed -n '/\[webservers\]/,/^\[/p' hosts | sed -r '/\[|^$/d'| xargs |sed 's/ /\,/g'
#!/bin/bash
get_groupname (){
sed -n '/^\[/p' hosts | sed -r 's#\[|\]##g'
}
get_hostnum () {
sed -rn '/\['$1'\]/,/^\[/p' hosts | sed -r '/^\[|^$/d' | wc -l
}
get_host () {
sed -rn '/\['$1'\]/,/^\[/p' hosts | sed -r '/^\[|^$/d' | xargs |sed 's/ /\,/g'
}
for host in $(get_groupname)
do
echo "主机组名: $host ,$host 中包含 $(get_hostnum $host) 台主机 ,主机地址:$(get_host $host)"
done