linux三剑客之sed
sed(Stream Editor,流编辑器),对标准输出或文件逐行进行处理
语法格式
第一种形式:stdout | sed [option] "pattern command"
第二种形式:sed [option] "pattern command file"
选项(option)
|
选项 |
含义 |
例子 |
|
-n |
只打印模式匹配行,不打印原来的行(一般都会加该参数) |
sed '/python/p' sed.txt I love python I love python I love PYTHON
sed -n '/python/p' sed.txt I love python |
|
-e |
直接在命令行进行sed编辑,默认选项(连接多个"pattern command"的组合) |
sed -n -e '/pthon/p' -e '/PYTHON/p' sed.txt |
|
-f |
将匹配模式和命令的组合("pattern command")保存到文件中,指定文件执行 |
vim edit.sed /python/p sed -n -f edit.sed sed.txt |
|
-r |
支持扩展正则表达式 |
sed -n -r '/python|PYTHON/p' sed.txt |
|
-i |
直接修改文件内容(sed默认不会对原文件进行修改) |
sed -n -i 's/love/like/g;p' sed.txt |
匹配模式(pattern)
pattern匹配模式,即过滤条件,如果没有匹配模式,默认对所有行进行command处理,如果有匹配模式,先根据匹配模式过滤出相匹配的行,然后再对其逐行执行command
|
匹配模式 |
含义 |
|
10command |
匹配到第10行 |
|
10,20command |
匹配从第10行开始,到第20行结束 |
|
10,+5command |
匹配从第10行开始,到第16行结束 |
|
/pattern1/command |
匹配到包含pattern1的行(支持正则) |
|
/pattern1/,/pattern2/command |
匹配到包含pattern1的行开始,到匹配到包含pattern2的行结束 |
|
10,/pattern1/command |
匹配从第10行开始,到匹配到包含pattern1的行结束 |
|
/pattern1/,10command |
匹配到包含pattern1的行开始,到第10行结束 |
|
备注:$作为pattern时,表示最后一行 |
|
编辑命令(command)
|
类别 |
命令 |
含义 |
例子 |
|
查询 |
p |
打印(默认命令) |
|
|
增加 |
a |
行后追加(匹配行后一行) |
sed -i '/\/bin\/bash/a This is user which can login to system' /etc/passwd |
|
i |
行前追加(匹配行前一行) |
sed -i '/\/bin\/bash/i This is user which can login to system' /etc/passwd |
|
|
r |
外部文件读入,行后追加(匹配行后一行追加外部文件的内容) |
sed -i '/root/r list.txt' passwd |
|
|
w |
匹配行写入外部文件(将匹配到的行写入其他文件中) |
sed -i '/root/w /tmp/user_login.txt' passwd |
|
|
删除 |
d |
删除 |
|
|
修改 |
s/old/new/ |
将行内第一个old替换成new |
|
|
s/old/new/2 |
将行内第二个old替换成new |
|
|
|
s/old/new/g |
将行内全部的old替换成new |
sed -i 's/\/bin\/bash/\/BIN\/BASH/g' passwd |
|
|
s/old/new/2g |
同一行内,替换从第2个开始到剩下所有符合条件的字符串 |
|
|
|
s/old/new/ig |
将行内全部的old替换成new,忽略大小写 |
|
|
|
显示行号 |
= |
查看行号,但不显示内容 |
显示包含/bin/bash的行的行号 sed -n '/\/bin\/bash/=' passwd |
反向引用
&和\1 引用模式匹配到的整个串
&只能表示匹配到的完整字符串,只能引用整个字符串;而\1可以使用()来表示需要引用的字符串,并且\1可以扩展\2、\3等,顺序和前面()的顺序一致
举例
# 在test.txt文件中所有的had..p后面加入一个字符s,比如hadAAps、hadBBps [root@VM_0_13_centos ~]# cat test.txt hadAAp is a bigdata frame Spark hadBBp Kafka Skill on hadCCp Paper of hadDDp Google hadEEp # sed -i 's/\(had..p\)/\1s/g' test.txt与下面命令等价 [root@VM_0_13_centos ~]# sed -i 's/had..p/&s/g' test.txt [root@VM_0_13_centos ~]# cat test.txt hadAAps is a bigdata frame Spark hadBBps Kafka Skill on hadCCps Paper of hadDDps Google hadEEps # 将上述修改过的文件中的s去除 [root@VM_0_13_centos ~]# sed -i 's/\(had..p\)s/\1/g' test.txt [root@VM_0_13_centos ~]# cat test.txt hadAAp is a bigdata frame Spark hadBBp Kafka Skill on hadCCp Paper of hadDDp Google hadEEp # 将上述修改后的文件中had..p中的两个字符改为II [root@VM_0_13_centos ~]# sed -i 's/\(had\)..\(p\)/\1II\2/g' test.txt [root@VM_0_13_centos ~]# cat test.txt hadIIp is a bigdata frame Spark hadIIp Kafka Skill on hadIIp Paper of hadI
sed中引用变量
1.匹配模式中存在变量,则建议使用双引号(推荐方法)
2.sed中需要引入自定义变量时,如果外面使用单引号,则自定义变量也必须使用单引号
举例
以上两种方式任选其一,但是建议使用第一种方式,即pattern command使用双引号括起来,即"pattern command"
#!/bin/bash old_str=hadoop new_str=HADOOP
# 第一种方式 sed -i "s/$old_str/$new_str/g" test.txt
# 第二种方式 # sed -i 's/'$old_str'/'$new_str'/g' test.txt
利用sed查询特定内容
1.打印/etc/passwd中第20行的内容
sed -n '20p' /etc/passwd
2.打印/etc/passwd中从第8行开始,到15行结束的内容
sed -n '8,15p' /etc/passwd
3.打印/etc/passwd中从第8行开始,然后+5行结束的内容
sed -n '8,+5p' /etc/passwd
4.打印/etc/passwd中开头匹配hdfs字符串的内容
sed -n '/^hdfs/p' /etc/passwd
5.打印/etc/passwd中开头为root的行开始,到开头为hdfs的行结束的内容
sed -n '/^root/,/^hdfs/p' /etc/passwd
6.打印/etc/passwd中第8行开始,到含有/sbin/nologin的内容的行结束的内容
sed -n '8,/\/sbin\/nologin/p' /etc/passwd
7.打印/etc/passwd中第一个包含/bin/bash内容的行开始,到第5行结束的内容
sed -n '/\/bin\/bash/,5p' /etc/passwd
利用sed删除特定内容
1.删除/etc/passwd中的第5行
sed -i '15d' /etc/passwd
2.删除/etc/passwd中的第8行到第14行的所有内容
sed -i '8,14d' /etc/passwd
3.删除/etc/passwd中的不能登录的用户(筛选条件:/sbin/nologin)
sed -i '/\/sbin\/nologin/d' /etc/passwd
4.删除/etc/passwd中以mail开头的行,到以yarn开头的行的所有内容
sed -i '/^mail/,/^yarn/d' /etc/passwd
5.删除/etc/passwd中第一个不能登录的用户,到第13行的所有内容
sed -i '/\/sbin\/nologin/,13d' /etc/passwd
6.删除/etc/passwd中第5行到以ftp开头的所有行的内容
sed -i '5,/^ftp/d' /etc/passwd
7.删除/etc/passwd中以yarn开头的行到最后行的所有内容
# $表示最后一行
sed -i '/^ftp/,$d' /etc/passwd
8.删除/etc/passwd中不能登录的所有用户
sed -i "/\/sbin\/nologin/d" /etc/passwd
9.删除配置文件中的所有注释行和空行
# 在sed中连续执行两个"pattern command",使用;连接,即"pattern1 command1;pattern2 command2"
sed -i '/[:blank:]*#/d;/^$/d' /etc/nginx/nginx.conf
10.在配置文件中所有不以#开头的行前面添加*字符,注意:以#开头的行不添加
sed -i 's/^[^#]/\*&/g' /etc/nginx/nginx.conf
利用sed修改文件内容
|
修改命令对照表 |
|
|
编辑命令 |
含义 |
|
1s/old/new/ |
将第一行中的old替换成new |
|
1,10s/old/new/ |
将第一行到第十行中的old替换成new |
|
1,+5s/old/new/ |
将第一行到第六行中的old替换成new |
|
/pattern1/s/old/new/ |
将匹配到pattern1的行中的old替换成new |
|
/pattern1,/pattern2/s/old/new/ |
将匹配到pattern1的行直到匹配到pattern2的所有行中的old替换成new |
|
/pattern1/,10s/old/new/ |
将匹配到pattern1的行到第10行的所有行中的old替换成new |
|
10,/pattern1/s/old/new/ |
将第10行直到匹配到pattern1的行中的old替换成new |
修改/etc/passwd中第1行中第一个root为ROOT
sed -i '1s/root/ROOT/' /etc/passwd
修改/etc/passwd中第5行到第10行中所有的/sbin/nologin为/bin/bash
sed -i '5,10s/\/sbin\/nologin/\/bin\/bash/g' /etc/passwd
修改/etc/passwd中匹配到/sbin/nologin的行,将匹配到行中的login改为LOGIN
sed -i '/\/sbin\/nologin/s/login/LOGIN/g' /etc/passwd
修改/etc/passwd中从匹配到以root开头的行,到匹配到行中包含mail的所有行,将这些所匹配到的行中的bin改为HADOOP
sed -i '/^root/,/mail/s/bin/HADOOP/g' /etc/passwd
修改/etc/passwd中从匹配到以root开头的行,到第15行,将这些所匹配到的行中的nologin改为SPARK
sed -i '/^root/,15s/nologin/SPARK/g' /etc/passwd
修改/etc/passwd中从第15行,到匹配到以yarn开头的行,将这些所匹配到的行中的bin改为BIN
sed -i '15,/^yarn/s/bin/BIN/g' /etc/passwd
利用sed追加文件内容
|
追加 |
a |
行后追加(匹配行后一行) |
sed -i '/\/bin\/bash/a This is user which can login to system' /etc/passwd |
|
i |
行前追加(匹配行前一行) |
sed -i '/\/bin\/bash/i This is user which can login to system' /etc/passwd |
|
|
r |
外部文件读入,行后追加(匹配行后一行追加外部文件的内容) |
sed -i '/root/r list.txt' passwd |
|
|
w |
匹配行写入外部文件(将匹配到的行写入其他文件中) |
sed -i '/root/w /tmp/user_login.txt' passwd |
a
1.passwd文件第10行后面追加“Add Line Behind”
sed -i '10a Add Line Behind' passwd
2.passwd文件第10行到第20行,每一行后面都追加“Test Line Behind”
sed -i '10,20a Test Line Behind' passwd
3.passwd文件匹配到/bin/bash的行后面追加“Insert Line For /bin/bash Behind”
sed -i '/\/bin\/bash/a Insert Line For /bin/bash Behind '
i
1.passwd文件匹配到以yarn开头的行,在匹配行前面追加“Add Line Before”
sed -i '/^yarn/i Add Line Before ' passwd
2.passwd文件每一行前面都追加“Insert Line Before Every Line”
sed -i 'i Insert Line Before Every Line' passwd
r
1.将/etc/fstab文件的内容追加到passwd文件的第20行后面
sed -i '20r /etc/fstab' passwd
2.将/etc/inittab文件内容追加到passwd文件匹配/bin/bash行的后面
sed -i '/\/bin\/bash/r /etc/inittab' passwd
3.将/etc/vconsole.conf文件内容追加到passwd文件中特定行后面,匹配以ftp开头的行,到第18行的所有行
sed -i '/^ftp/,18r /etc/vconsole.conf' passwd
w
1.将passwd文件匹配到/bin/bash的行追加到/tmp/sed.txt文件中
sed -i '/\/bin\/bash/w /tmp/sed.txt' passwd
2.将passwd文件从第10行开始,到匹配到hdfs开头的所有行内容追加到/tmp/sed.txt
sed -i '10,/^hdfs/w /tmp/sed.txt' passwd
示例:处理一个类似MySQL配置文件my.cnf的文本,示例如下:
编写脚本实现以下功能:输出文件有几个段([mysqld]这样是一个段),并且针对每个端可以统计配置参数总个数
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under a different user or group,
# customize your systemd unit file for mariadb according to the
# instructions in http://fedoraproject.org/wiki/Systemd
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
#
# include all files from the config directory
#
!includedir /etc/my.cnf.d
预想输出结果
1: mysqld 3
2: mysqld_safe 2
结构
function get_all_segment
{
sed -n 's/^\[\(.*\)\]$/\1/p' /etc/my.cnf
}
function count_items_in_segment
{
sed -n '/^\['$1'\]$/,/^\[.*\]$/p' /etc/my.cnf | grep -vE "^#|^$|^\[.*\]$|^\!"|wc -l
}
代码
[root@VM_0_13_centos ~]# cat mysql_process.sh
#!/bin/bash
FILE_NAME=/etc/my.cnf
function get_all_segment
{
echo "`sed -n 's/^\[\(.*\)\]$/\1/p' $FILE_NAME`"
}
function count_items_in_segment
{
echo "`sed -n '/^\['$1'\]$/,/^\[.*\]$/p' $FILE_NAME | grep -vE "^#|^$|^\[.*\]$|^\!"|wc -l`"
}
index=1
for segment in `get_all_segment`
do
items_count=`count_items_in_segment $segment`
echo "$index: $segment $items_count"
index=`expr $index + 1`
done
[root@VM_0_13_centos ~]# sh mysql_process.sh
1: mysqld 3
2: mysqld_safe 2

浙公网安备 33010602011771号