sed工具概述

Stream Editor,流式编辑器

  • 非交互,基于模式匹配过滤及修改文本
  • 逐行处理,并将结果输出到屏幕
  • 可实现对文件的输出、删除、替换、复现、剪切、导入,导出等各种操作

    命令格式解析

    主要用法

    格式1:前置命令 | sed [选项] ‘编辑指令’
    举例:将单词首字母大写
    1. echo 'welcome to my home' | sed 's#\w#\u&#'
    Sed—流式编辑工具 - 图1
    格式2:sed [选项] ‘编辑指令’ 文件…
    举例:读取/proc/meminfo中的第1行
    1. sed -n '1p' /proc/meminfo
    Sed—流式编辑工具 - 图2

    常用参数选项

    | 选项 | 作用 | | —- | —- | | -n | 屏蔽默认输出 | | -i | 直接修改文件内容 | | -r | 启用扩展的正则表达式,若与其它选项一起使用应作为首个选项 | | -e | 可以指定多个处理动作 | | -f | 编辑动作保存在文件中,指定文件执行,此方式为sed脚本方式 | | -{} | 可能组合多个命令,以分号分隔 |

定址符

作用:

  • 用来指定处理的起、止行数
  • 省略定位符时,默认逐行处理全部文本
  • 地址可表示为文本的”行号”,或者用来匹配的”/正则表达式/“ | 匹配模式 | 含义 | | —- | —- | | 10command | 匹配到第10行 | | 10,20command | 匹配从第10行开始,到第20行结束 | | 10,+5cmmand | 匹配从第10行开始,到第16行结束 | | /pattern1/command | 匹配到pattern1的行 | | /pattern1/,/pattern2/command | 匹配到pattern1的行开始,到匹配到pattern2的行结束 | | 10,/pattern1/command | 匹配从第10行开始,到匹配到pettern1的行结束 | | /pattern1/,10command | 匹配到pattern’的行开始,到第10行匹配结束 |

处理命令

命令列表

类别 动作 含义
查询 p 打印
增加 a 行后追加
i 行前追加
r 外部文件读入,行后追加
w 匹配行写入外部文件
删除 d 删除
替换 s/old/new/g 将行内的old全部替换成new
s/old/new/2g 将行内从第2个开始及以后old全部替换成new
s/old/new/ig 将行内的old全部替换成new,忽略大小写

拓展:

  • 替换操作的分享**"/"**可改用其它字符,如**#、&、!**,便于修改文件路径
  • 打印操作使用**=**可以输出行号,例如**sed -n '/^mail/{=;p}' /etc/passwd**

    基本使用

    拷贝/etc/hosts文件测试,利用sed以下任务
    1.删除文件 中每行的第二个、最后一个字符

  • 思路:第1次删掉第1个,第二次删掉第2个

    1. sed 's#.##2;s#.$##' hosts

    Sed—流式编辑工具 - 图3
    2.删除文件中每行的第二个、最后一个单词

  • 思路:分两次替换操作,第一次替换掉第2个单词,第二次替换掉最后一个单词

    1. sed -r 's#[a-Z]+##2;s#[a-Z]+([^a-Z]*)$#\1#' hosts

    Sed—流式编辑工具 - 图4
    3.将文件中每行的第一个、第二个字符互换

  • 方法:每行文本拆分为”第1个字符”、”第2个字符”、”剩下的所有字符”三个部分,然后通过替换操作重排顺序为”2-1-3”

    1. sed -r 's;(.)(.)(.+);\2\1\3;' hosts

    Sed—流式编辑工具 - 图5
    4.将文件中每行的第一个、第二个单词互换

  • 方法:每行文本拆分为”第1个单词”、”单词分隔”、”第2个单词”、”剩下的所有字符”四个部分,然后通过替换操作重排顺序为”3-2-1-4”

    1. sed -r 's#([a-Z]+)([^a-Z]*)([a-Z]+)(.*)#\3\2\1\4#' hosts

    Sed—流式编辑工具 - 图6
    5.删除文件中所有的数字、行首的空格

  • 方法:分两次替换,第1次替换数字,第2次替换空格

Sed—流式编辑工具 - 图7
6.为文件中每个小写字母添加括号

  • 方法:使用”&”可调用s替换操作中的整个查找串

Sed—流式编辑工具 - 图8
7.编辑一个sed脚本

  • 将所有单词首字母大写
  • 将所有空行删掉
  • 在每一行后面添加换行

1.脚本内容

  1. s;([a-Z]+)([^a-Z]*);\u\1\2;g
  2. /^$/d
  3. /[^\S]/a\\

2.运行脚本

  1. sed -r -f script.sed hosts

Sed—流式编辑工具 - 图9

shell中变量的引用

1.匹配模式中存在变量,则建议使用双引号

  1. sed "s/$old_str/$new_str"

2.sed中需要引入自定义变量时,如果外面使用单引号,则自定义变量也必须使用单引号

  1. sed 's/'$old_str'/'$new_str''

反向引用

&和\1:引用模式匹配到的整个串
例1:使用**&**给/etc/passwd中的以r开头t结尾的4字母单词添加上括号

  1. sed 's/r..t/[&]/g' /etc/passwd |head -1

Sed—流式编辑工具 - 图10
例2:使用**\1**给/etc/passwd中的以r开头t结尾的4字母单词添加上括号

  1. sed -r 's/(r..t)/<*\1*>/g' /etc/passwd |head -1

Sed—流式编辑工具 - 图11
上面两种方式实现了一样的功能,分别使用&\1引用前面匹配到的字符串
两者区别在于:

  • &匹配到的是完整的字符串,只能引用整个字符串
  • \1可以使用()对匹配的字符进行引用

例如:如果我们仅想替换匹配到的字符串的一部分,则必须使用\1这种方式。
需求:现在想把sshd_config文件中的允许root登录改成不允许root登录
Sed—流式编辑工具 - 图12
这里使用正则的反向引用来完成,将yes改成no
Sed—流式编辑工具 - 图13

查询用法

命令对照表

命令 功能
1p 打印第1行内容
1,10p 打印1行到10行的内容
1,+5p 打印1行到6行的内容
/pattern1/p 打印每行中匹配到pattern1的行内容
/pattern1/,/pattern2/p 打印匹配到pattern1的行直到匹配到pattern2的所有行内容
/pattern1/,10p 打印匹配到pattern1的行到10行的所有行内容
10,/pattern1/p 打印第10行直到匹配到pattern1的所有行内容

练习举例

1.打印/etc/passwd中第20行的内容

  1. sed -n '20p' /etc/passwd

Sed—流式编辑工具 - 图14
2.打印/etc/passwd从第6行开始,到第15行结束的内容

  1. sed -n '8,15p' /etc/passwd

Sed—流式编辑工具 - 图15
3.打印/etc/passwd从第18行开始,然后+3行结束的内容
Sed—流式编辑工具 - 图16
4.打印/etc/passwd中以内容为**sys**开头的行
Sed—流式编辑工具 - 图17
5.打印/etc/passwd中以root开始的行,到开头为**sys**的行结束
Sed—流式编辑工具 - 图18
6.打印/etc/passwd从24行开始,到行结尾含有**nologin**的内容结束
Sed—流式编辑工具 - 图19
7.打印/etc/passwd中第一个以**bash**结尾的字符串开始,到第5行结束
Sed—流式编辑工具 - 图20
注意了:

  • 这里找到以bash结尾字符串的行是在第38行,我们给的条件是第5行结束
  • 这里输出的结果只要38一行,所以得出结论,找到的行 > 结束行,那么结束的行就等于找到的行

    其它补充

    | 示例 | 含义解析 | | —- | —- | | sed -n ‘p’ msg.txt | 输出所有行,等同于cat msg.txt | | sed -n ‘4p’ msg.txt | 输出第4行 | | sed -n ‘4,7p msg.txt | 输出第4~7行 | | sed -n ‘4,+10p’ msg.txt | 输出第4行及其后的10行内容 | | sed -n ‘/^bin/p’ msg.txt | 输出以bin开头的行 | | sed -n ‘p;n’ msg.txt | 输出奇数行,n表示读入下一行文本(隔行) | | sed −n’n;p’ msg.txt | 输出偶数行,n表示读入下一行文本(隔行) | | sed -n ‘10,${n;p}’ msg.txt | 输出从第10行至文件末尾的所有偶数行 | | sed −n’$=’ msg.txt | 输出文件的行数 |

删除内容

命令对照表

查询命令 含义
1d 删除第1行内容
1,10d 删除1行到10行的内容
1,+5d 删除1行到6行的内容
/pattern1/d 删除每行中匹配到pattern1的行内容
/pattern1/,/pattern2/d 删除匹配到pattern1的行直到匹配到pattern2的所有行内容
/pattern1/,10d 删除匹配到pattern1的行到10行的所有行内容
10,/pattern1/d 删除第10行直到匹配到pattern1的所有行内容

练习举例

1.删除/etc/passwd中第1行

  1. sed '1d' /etc/passwd

2.删除/etc/passwd中第6,21行的所有内容

  1. sed '6,21d' /etc/passwd

3.删除/etc/passwd中不是以bash或zsh内容结尾的用户

  1. sed -r '/bash$|zsh$/!d' /etc/passwd

Sed—流式编辑工具 - 图21
4.删除/etc/passwd中以sys开头到以mail开头的行的所有内容

  1. sed '/^mail/,/^system/d' /etc/passwd

Sed—流式编辑工具 - 图22
5.删除/etc/passwd中第1个不能登录的用户,直到15行的所有内容

  1. sed -r '/nologin|false/,15d' /etc/passwd

Sed—流式编辑工具 - 图23
注意:

  • 这个输出的结果和我们想的有差距,nick是在/etc/passwd文件中的最后一行
  • 但是我们的条件是直到15行为止,它并没有到了15行就结束而是继续往下匹配
  • 所以在实际的运用中不推荐这种方式,推荐下面这种数字在前表达式在后的方式

6.删除/etc/passwd中第3行到以sshd开头的所有行内容

  1. sed '3,/^sshd/d' /etc/passwd

Sed—流式编辑工具 - 图24
7.删除/etc/passwd中以nobody开头的行到结尾行所有的内容

  1. sed '/^mail/,/$$/d' /etc/passwd

Sed—流式编辑工具 - 图25
8.删除/etc/passwd中不能登录的所有用户

  1. sed -r '/nologin|false$/d' /etc/passwd

Sed—流式编辑工具 - 图26

其它补充

命令 功能
sed ‘1,3n’ myfile 删除第3-5行
sed ‘/html/d’ myfile 删除所有包含html的行
sed ‘/html/!d’ myfile 不删除所有包含html的行
sed ‘/^#/d’ myfile 删除以#号开头的行
sed ‘$d’ myfile 删除最后一行
sed ‘/^$/d’ myfile 删除所有的空行
sed ‘/^$/{n;/^$/d}’ myfile 删除重复空行,连续两个空行只保留一个

替换用法

命令对照表

编辑命令 含义
1s/old/new/ 替换第1行内容old为new
1,10s/old/new/ 替换1行到10行的内容old为new
1,+5s/old/new/ 替换1行到6行的内容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/oId/new/ 替换第10行直到匹配到pattern1的所有行内容old为new

练习举例

s/old/new

1.在行尾添内容

  1. echo "hahalalayayaxixi" | sed "s/$/-wawawawaw/"

2.将所有的小写字母转成大写(**\u**是把下一个字符转成大写upper)

  1. echo "hello everyone" | sed 's/[a-z]/\u&/g'

3.将所有的大写转换成小写(**\l**是把下一个字符转成小写lower)

  1. echo "HELLO SHENQI"| sed 's/[A-Z]/\l&/g'

1s/old/new/1

1.将第一行第一个小写字符替换成大写字符

  1. echo "how are your yayayay\~\~\~" |sed '1s/[a-z]/\\u&/1'

3,6,s/old/new/2

1.将.bashrc文件中第3行到第5行的第二个空格替换成*** * ***

  1. sed '3,6s/ /***/2' ~/.bashrc

2,+4s/old/new/3

1.将/etc/passwd文件中,从第2行开始往后数4行的第3个字母,用**()**括起来

  1. sed '2,+4s/[A-Za-z]/(&)/3' /etc/passwd|head

/pattern1/s/old/new/3gp

1.匹配/etc/passwd文件中以字母或者数字开头的行,并且长度大于等于10,并把它们第3位数字及以后的数字加上**()**

  1. sed -rn '/^[a-zA-Z0-9]{10,}/s/[0-9]/(&)/3gp' /etc/passwd

/pattern1/,/pattern2/s/old/new/g

1.匹配所有的if代码块,将里面的.替换成source

  1. sed -rn '/^if/,/^fi/s/ {1,}+\./source/p' ~/.bashrc

15,/pattern1/s/old/new/ig

1.从第15行开始匹配/etc/passwd文件中结尾是**/usr/sbin/nologin**的行并将它们全部替换成**/bin/false**

  1. sed -rn -e '15,/.+/{=;s#/usr/sbin/nologin$#/bin/false#p}' /etc/passwd

Sed—流式编辑工具 - 图27

其它补充

示例 含义解析
sed ‘s/html/HTML/‘ tmp.txt 将每行中第一个html替换为HTML
sed ‘s/html/HTML/3’ tmp.txt 将每行中的第3个html替换为HTML
sed ‘s/html/HTML/g’ tmp.txt 将所有的html都替换为HTML
sed ‘s/html//g’ tmp.txt 将所有的html都删除(替换的空串)
sed ‘s/doc/&s/g’ tmp.txt 将所有的doc都替换为docs,&代表匹配到的串
sed ‘3,9s/^/#/‘ tmp.txt 将第3~9行注释掉(行首加#号)
sed ‘s/^#sys/sys/‘ tmp.txt 解除以#sys开头的行的注释(去除行首的#号)

追加用法

命令 作用
a 在匹配行后面追加内容
i 在匹配行前追加内容
c 替换当前行

a—append

1.复制passwd文件到家目录,在文件中第1,10行追加system user

  1. cp /etc/passwd ~/
  2. sed -i '1,10asystemuser' ~/passwd

Sed—流式编辑工具 - 图28
2.在passwd文件中将所有以bash或zsh结尾的用户后追加login user

  1. sed -r '/(bash|zsh)$/a login user' ~/passwd

Sed—流式编辑工具 - 图29

i—insert

1.将uname -a 的结果,插入到/etc/issue第1行。

  1. kernel=`uname –a`
  2. sed -i "1i$kernel" /etc/issue

2.将echo $USER login 插入到家目录下的.bashrc文件中第1行

  1. sed -i '1iecho $USER login' \~/.bashrc

c—change

1.将sshd_config配置文件中PermitRootLogin设置成yes

  1. sed -ri '/#PermitRootLogin/c PermitRootLogin yes' /etc/ssh/sshd_config

Sed—流式编辑工具 - 图30

导入导出

基本动作

  • r 动作应结合-i选项才会存入,否则只输出
  • w 动作以覆盖的方式另存为新文件 | 命令 | 作用 | | —- | —- | | r | 将文件内容追加到匹配行后面 | | w | 将匹配行写入指定文件 |

r—read

1.

  • 读取/etc/fstab放到标准输出的第一行后面
  • 此方法也是在文件中开头与结尾添加内容最快的方法

    1. echo -e "#这是开机分区挂载文件\n#以上就是分区内容" |sed '1r /etc/fstab'

    Sed—流式编辑工具 - 图31
    2.读取welcome.php文件中的内容,放到index.php的<?php到最后一行之间

    1. sed '/<?php/r welcome.php' index.php

    welcome.php文件内容

    1. echo "<h1>这是我的第一个网页</h1>";

    index.php文件内容

    1. <?php
    2. phpinfo();
    3. ?>

    执行结果
    Sed—流式编辑工具 - 图32

    w-write

    1.匹配/etc/passwd以bash或zsh结尾的行,写到**login_ok**文件中

    1. sed -rn '/(bash|zsh)$/w login_ok' /etc/passwd

    Sed—流式编辑工具 - 图33
    2.将/var/log/auth.log从第1行开始往后数9行放到**top10.msg**文件中

    1. sed -n '1,+9w top10.msg' /var/log/messages

    Sed—流式编辑工具 - 图34

    复制剪切

    模式空间

  • 存放当前处理的行,将处理结果输出

  • 若当前行不符合处理条件,则原样输
  • 处理完当前行再读入下一行来处理

    保持空间

  • 作用类似于”剪贴板”

  • 默认存放一个空行(换行符 \n)

    基本动作

  • H:模式空间——【追加】——>保持空间

  • h:模式空间——【覆盖】——>保持空间
  • G:保持空间——【追加】——>模式空间
  • g:保持空间——【覆盖】——>模式空间
  • 小结:H/h——>复制,G/g——>粘贴

    复制示例

    1.将/etc/passwd前9行内容写到/tmp/pass文件中
    1. head -9 /etc/passwd > /tmp/pass
    2.将1到3行复现到文件结尾
    1. sed '1,3H;$G' /tmp/pass
    Sed—流式编辑工具 - 图35

    命令执行后发现图中方框内存在一个空行,是因为保持空间里面默认就是一个空行

3.改用下列方式可避免出现空行

  1. # 原理就是将第1行覆盖到保持空间
  2. sed '1h;2,3H;$G' /tmp/pass

Sed—流式编辑工具 - 图36

剪贴示例

1.将文件前3行剪切到文件结尾

  1. sed '1h;2,3H;1,3d;$G' /tmp/pass

Sed—流式编辑工具 - 图37

sed流控制

!取反操作

用途:

  • 根据定址条件取反

示例

  • 列出shell环境不是nologinfalse的用户账号记录

Sed—流式编辑工具 - 图38

n读下一行

用途

  • 读入下一行进行处理(产生隔行/跳行的效果)

示例

  • 分别列出文件的奇数/偶数行

1.输出奇数行
Sed—流式编辑工具 - 图39
2.输出偶数行
Sed—流式编辑工具 - 图40