Back
Featured image of post 文本处理三剑客之sed

文本处理三剑客之sed

从零基础出发, 理解 sed 的工作模式, 以及 sed 的常用编辑指令, 最后带你利用 sed 进行 mysql 配置文件的脚本练习

sed 工作模式

sed 是流编辑器, 对标准输出文件逐行处理

匹配 + 执行 : 默认会打印原始信息, 还会打印执行后的结果

语法格式:

  1. stdout | sed [option] “pattern command”
  2. sed [optoin] “pattern command”

pattern 是可选的

sed 参数

选项 含义
-n 静默模式
-e 进行多条匹配规则
-f 使用文件, 文件为匹配规则
-r 支持扩展正则表达式
-i 直接修改文件内容
$ sed -n '/python/p' set.txt  # p 为打印操作

$ sed -n -e '/python/p' -e '/PYTHON/p' sed.txt  # 执行多条

# print.sed: /python/p
$ sed -n -f print.sed sed.txt

$ sed -n -r '/python|PYTHON/p' sed.txt

# g: 全部修改; p: 打印到终端; -i 直接修改到文件
$ sed -i 's/love/like/g;p' sed.txt

pattern 用法

匹配模式

匹配模式 含义
10command 匹配第 10 行
10,20command 从第 10 行开始, 到第 20 行结束
10,+5command 从第 10 行开始, 到第 16 行结束
/pattern1/command (//d) 匹配 pattern1 的行
/pattern1/,/pattern2/command (//,//p) 匹配 pattern1 的行开始, 到 pattern2 的行结束
10,/pattern1/command 从第 10 行开始, 到匹配 pattern1 的行结束
/pattern1/,10command 从匹配 pattern1 的行开始, 到第 10 行结束
$ sed -n '10p' /etc/passwd
$ sed -n '10,20p' /etc/passwd
$ sed -n '10,+5p' /etc/passwd

$ sed -n '/^root/p' /etc/passwd

$ sed -n '/^root/,/^nginx/p' /etc/passwd

$ sed -n '/4,/^nginx/p' /etc/passwd
$ sed -n '/^root/,10p' /etc/passwd

sed 编辑命令

打印

命令 含义
p 打印
$ sed '/^root/p' /etc/passwd

删除

命令 含义
d 删除行
$ sed -i '/\/sbin\/nologin/d' passwd

$ sed -i '/^mail/,/^ftp/d' passwd

增加

命令 含义
a 行后追加
i 行前追加
r 从外部读入文件, 追加到行后
w 把结果写到对应文件
$ sed -i '/^root/,/^nginx/a AAAAAA' passwd  # 匹配到的每一行后追加

$ sed -i '/^root/,/^nginx/i AAAAAA' passwd  # 匹配到的每一行前追加

$ sed -i '/root/,/nginx/r ./list' passwd

$ sed -n '/\/bin\/bash/w /tmp/login' passwd

显示行号

命令 含义
= 显示行号
$ sed '/\/bin\/bash/=' passwd

修改

命令 含义
s/旧/新/ 更改每行第一个
s/旧/新/3 更改每行第一个
s/旧/新/3 更改每行所有
s/旧/新/2g 更改每行第 2 开始所有
s/旧/新/ig 更改每行所有, 忽略大小写
$ sed -i 's/HADOOP/hadoop/' file

$ sed -i 's/HADOOP/hadoop/2' file

$ sed -i 's/HADOOP/hadoop/g' file

$ sed -i 's/HADOOP/hadoop/2g' file

$ sed -i 's/HADOOP/hadoop/ig' file

反向引用

&\1 , \1需要与()一起使用(部分引用时)

$ sed -i 's/had..../&s/g' file
$ sed -i 's/had..../\1s/g' file

$ sed -i 's/\(had=)..../\1DOOP/g' file

变量引用

  1. 双引号
  2. 单引号变量
$ sed -i "s/$str1/str2/g" file

$ sed -i 's/'$str1'/'$str2'/g' file

脚本练习: 查询 mysql 配置文件

知识点:

利用sed进行文件查询

预期:

mysqld's num: 22
client's num: 1
mysql's num: 1
server's num: 6

思路:

  1. 获取所有段
  2. 根据获取的段信息, 获取每一段下的配置项数目
  3. 打印结果
#!/bin/bash
#

FILENAME="/root/sed/my.ini"

# 1. 获取所有段
function get_segments
{
    item=`sed -n '/\[.*\]/p' $FILENAME | sed 's/\[//g' | sed 's/\]//g'`
    echo $item
}

# 2. 根据获取的段信息, 获取每一段下的配置项数目
function count_segment_num
{
    # 根据 sed 的范围匹配
    # 根据参数提供段范围匹配                       | 去除 [ 开头   | 去除 # 开头  | 去除空行
    items=`sed -n '/\['$1'\]/,/\[.*\]/p' $FILENAME | grep -v "^\[" | grep -v "^#" | grep -v "^$"`

    # 统计所有项
    index=0
    for item in $items
    do
        index=`expr $index + 1`
    done

    echo $index
}

for seg in `get_segments`
do
    item_count=`count_segment_num $seg`
    echo "${seg}'s num: $item_count"
done

sed 文本练习

文本删除:

删除空行和注释行

$ sed -i '/^#/d' nginx.conf  # 删除开头 #

$ sed -i '/^$/d' nginx.conf  # 删除空行

$ sed -i '/[:blank]*#/d' nginx.conf  # 删除 # 前有空格

# 合并写法
$ sed -i '/[:blank]*#/d;/^$/d' nginx.conf

对以非 # 开头行加 *

# 非 # : [^#]
$ sed -i 's/^[^#]/\*&/g' nginx.conf

文本查找

匹配到以 root 开始的行, 把 login 改为 LOGIN

sed -i '/^root/s/login/LOGIN/' passwd

修改以 root 开始的行, 到包含 mail 的行, 修改 bin 为 BIN

sed -i '/^root/,/mail/s/bin/BIN/g' passwd

把文本中数字删除

sed -i 's/[0-9]*//g' file

文本追加

根据行号

$ sed -i '3,7/a Append' passwd

匹配到 /bin/bash 的行, 气候追加 After

$ sed -i '/\/bin\/bash/a After' passwd

以 nginx 开头的行前, 添加 Before

$ sed -i '/^nginx/i Before' passwd

每一行前加 Before

$ sed -i 'i Before' passwd

把 /etc/fstab 内容追加到含 /bin/bash 的行后

$ sed -i '/\/bin\/bash/r /etc/fstab' passwd

**把 /bin/bash 的行, 写入 /tmp/sed.txt **

$ sed -i '/\bin\/bash/w /tmp/sed.txt' passwd

把第 10 行到以 nginx 开头的行写入 /tmp/sed.txt

$ sed -i '10,/\bin\/bash/w /tmp/sed.txt' passwd