Shell--Sed 使用详解

1 概述

    Sed 全称 Stream editor,一个流线式的非交互式的编辑器。它每次读取一行放入模式空间缓冲区中,直到全部命令都执行完后把结果送往屏幕,而后读取下一行。由于是将输入内容复制到缓冲区处理,因此不会对原文件有任何影响,若是须要保存处理后的结果能够重定向生成新的文件。linux

    本文全部示例均基于txt.log文件,其中增长了行号。具体内容以下:bash

1 root:x:0:0:root:/root:/bin/bash
  2 bin:x:1:1:bin:/bin:/sbin/nologin
  3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
  4 adm:x:3:4:adm:/var/adm:/sbin/nologin
  5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
  6 sync:x:5:0:sync:/sbin:/bin/sync
  7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
  8 halt:x:7:0:halt:/sbin:/sbin/halt
  9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
 10 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
 11 operator:x:11:0:operator:/root:/sbin/nologin
 12 games:x:12:100:games:/usr/games:/sbin/nologin
 13 gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
 14 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
 15 nobody:x:99:99:Nobody:/:/sbin/nologin
 16 dbus:x:81:81:System message bus:/:/sbin/nologin
 17 vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
 18 abrt:x:173:173::/etc/abrt:/sbin/nologin
 19 haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
 20 ntp:x:38:38::/etc/ntp:/sbin/nologin
 21 saslauth:x:499:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin
 22 postfix:x:89:89::/var/spool/postfix:/sbin/nologin
 23 sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
 24 tcpdump:x:72:72::/:/sbin/nologin
 25 nscd:x:28:28:NSCD Daemon:/:/sbin/nologin

2 定址

    定址即指定sed 处理的范围,默认是输入内容的每一行。有两种方式:行号和正则。具体见下表ssh

2.1 方式一览

Sed 定址方式详解tcp

选项 含义 备注
x 第x行 sed -n '3p' /etc/passwd  输出第3行
$ 最后一行,固定写法 sed -n '$p' /etc/passwd
x~Nth 从第x行开始,返回每隔N行的 sed -n '1~2p' /etc/passwd  输出奇数行
x,y x 到 y 之间的行(包含x和y) sed -n '1,3p' /etc/passwd 输出1到3行
/pattern/ 查询包含模式的行 sed -n '/dae/p' /etc/passwd 打印含有dae的行
/pattern/,/pattern/ 包含两个模式间的 sed -n '/root/, /mail/p' /etc/passwd
/pattern/,x 模式跟行号间的 sed -n '/root/, 10p  /etc/passwd
x,/pattern/ 行号跟模式间的 sed -n '1,/da/p'  /etc/passwd
addr1, +N 从开始位置起的后N行 sed -n -e '1, +3p' -e   /etc/passwd
x,y! 除了x,y 以外的全部行 !表示在前边条件知足后,直接取反

2.2 示例

    行号或者单个模式的容易理解,再也不赘述。下边着重演示两个模式及行号与模式混用的细节。归纳讲,模式在前边,则进行屡次匹配直到最后一行;若是在后边,只发生一次匹配,若无匹配到有效行则默认处理到最后一行。先找出包含root 和 daemon的行,代码以下:   编辑器

sed -n '/root/p' txt.log #找出包含root的行
##======================
 # 1 root:x:0:0:root:/root:/bin/bash
 # 11 operator:x:11:0:operator:/root:/sbin/nologin
##======================

sed -n '/daemon/p' txt.log #找出包含daemon的行
##======================
 # 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
 # 19 haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
##======================

sed -n '/mail/p' txt.log #找出包含mail的行
##======================
 # 9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
##======================

 

  1. /pattern/, /pattern/ 模式   
    #找出包含root到daemon之间的行
    sed -n '/root/,/daemon/p' txt.log
    ##==========================
     # 分析可知root有两行(1,11),daemon有两行(3,19)
     # 匹配到第一行后,找daemon 在第三行,因此先输出1,3行
     # 因为起始的模式会屡次匹配,则发起第二次查找11行,因此返回11-19行
     # 从20行后继续找root,一直到最后一行,没有了,退出
    ##==========================
    
    #依据上述分析,查出/daemon/ 和 /mail/之间的行,结果是什么呢
    sed -n '/daemon/, /mail/p' txt.log
    ##==========================
     # 返回的结果是3-9行和19-25行
     # daemon(3,19),,mail(19),txt.log 共25行
     # sed -n '/mail/, /daemon/p' txt.log 返回哪些行呢,为何?
    ##==========================
     
  2. /pattern/, N
    #起始为模式时总会返回模式匹配的行
    sed -n '/root/, 8p' txt.log #输出1-8与11行
    sed -n '/mail/, 8p' txt.log #输出第9行

     

  3. N,pattern
    sed -n '2, /daemon/p' txt.log #输出2-3行,以最早找到的daemon为准
    sed -n '10,/mail/p' txt.log #输出10-25行,mail(9) 10行后未匹配,直到最后一行,

     

3 命令详解

3.1 sed 经常使用选项    

选项 释义 示例
-n 配合p命令使用,只打印匹配的行 sed -n '1,3p' txt.log  不加n是输出因此行与匹配行
-e 用于执行多个命令 sed -n  -e '/root/p' -e '/root/=' txt.log
-i 直接修改文件内容 sed -i '/root/Root/s' txt.log
-r 支持扩展正则  

3.2 插入

#匹配行后新加一行
sed '/root/anewafter' txt.log 
sed '10,$/anewafter' txt.log

#匹配行前新加一行
sed '/root/inewbefore' txt.log 
sed '10,$/inewbefore' txt.log

3.3 删除

#删除匹配的行,行内的删除用替换实现
sed '/root/d' txt.log

3.4 替换

替换命令有三个:s,c,y功能略有差别,另外在讲缓冲区时,也会涉及另外一种替换实现。post

#c 表示将匹配的全部行的内容替换成新的字符串
sed -i '/^SELINUX=/c\SELINUX=disabled' /etc/selinux/config
sed '1,10chello' txt.log #将1-10行的内容替换为hello

#y 一对一替换,字符数必须相等且不支持正则,不然报错
sed '1,10y/r/R/' txt.log # 将1-10行的小写r 换成大写R

#s 支持正则
##=======================
 # 支持元字符正则
 # 分组\(..\) s/\(love\)able/\1rs/  最多到\9
 # & 保存搜索字符  s/love/**&**/  将love 替换成 **love**
 # \<  /> 匹配单词开始和结尾
 # \{m,n\} 支持限定符
##=======================
sed '1,10s/^.*$/#&/' txt.log  #1-10行开头加上# 
sed 's/^/#/' txt.log

##=======================
 # 跟s配合的命令
 # p 打印  sed 's/r/R/p' 能够结合-n选项使用
 # g 替换每行全部出现的  sed -n 's/r/R/gp'
 # N 替换每行第N个  sed -n 's/r/R/2p'
 # w 将结果写入文件  sed 's/r/R/w output' txt.log
##=======================
sed -n '1,10s/r/R/p' txt.log  #把1-10行的r换成大写,每行的第一个
sed -n 's/\([Rr]\)oot/\1OOT/gpw output.res' txt.log

3.5 不经常使用命令

#将结果写入新文件 w
sed '1,5w head5.log' txt.log #匹配的1-5行写入head5.log且所有输出到屏幕

#从文件里读取 r 
sed '/root/r head5.log' txt.log #在匹配行后加上从文件中读取的内容

#退出命令q  表示完成指定地址匹配后当即退出
sed  '/root/ q' txt.log #匹配到第一个root 后当即退出

#显示控制字符 l
sed -n 'l' txt.log #打印出含有控制字符的行

#输出文件行号 =
sed -n '/root/=' txt.log #打印出匹配的行号

3.6 高级应用

包括多命令执行,缓冲区读写实现的移动和替换功能等。spa

##===============
 # 多命令有三种方式 sed -e '' -e '' 上边说过
 # 大括号{命令1;命令2}  如 sed -n '/root/{p;=}'
 # 分号间隔多个命令 '命令1;命令2'  如 sed 's/r/R/;s/b/B/'
##===============
sed -e 's/R/r/' -e 's/o/O/g' txt.log
sed 's/R/r/;s/o/O/g' txt.log
sed -n '/root/{s/R/r/;s/o/O/}' txt.log

#处理匹配行的下一行 n  sed -n '/root/{n;s/r/R/g;}'
sed  '/root/{n;y/b/B/;}' txt.log #{}中最后一条命令的分号不能省

##===============
 # 模式缓冲区和保持缓冲区
 # 命令h和H 将模式缓冲区的内容放到保持缓冲区 h 是覆盖 H是追加
 # 命令g和G 将保持缓冲区的内容放到模式缓冲区 g 是覆盖 G是追加
 # x 互换模式缓冲区和保持缓冲区的内容
 # 通常用于移动文本内部的行或是用某行替换某行
##===============
sed  '/root/h;/daemon/G' txt.log #将离daemon前边的最后的一个root 行追加到 daemon后边
sed '/root/h;/daemon/x;' txt.log #将daemon行替换为前边最后的一条root 行

4 练习题

为了强化记忆,基于txt.log 的内容提出了几个题目,分A,B,C 三级,欢迎在评论区亮出你的答案,想看标准答案别忘了打赏,看到后私信给你 :) ,再偷偷的告诉你一句,只要仔细看完教程,答案不在话下!3d

sed 强化练习code

A级
1. 打印出偶数行 sed -n '2~2p' txt.log 或 sed '1~2d' txt.log
2. 打印出不包含数字3或5的行 sed -n '/[35]/!p' txt.log
3. 在含有大写字母行的下边插入一空行,并将结果保存成blank_line.log  sed  '/[A-Z]/a\\n' txt.log > blank_line.log
4. 删除blank_line.log全部的空行并保存    sed -i '/^$/d' blank_line.log
B级
1. 删除每行第一个字母前的全部字符并保存为 nonu.log  sed -n 's/\([^A-Za-z]\{1,\}\)//pw none_num.log' txt.log
2. 将包含root的首行开头加上#,其它行不做处理  sed '/root/{s/^/#/;q;}' txt.log
3. 将全部的非零的一位数字前补零  sed -n  's/\<\([1-9]\{1\}\)\>/0\1/gp' txt.log
C级
1. 删除含有root行下的连续3行   sed '/root/, +3d' txt.log
2. 互换包含root 和  daemon的行  
相关文章
相关标签/搜索