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的行  
相關文章
相關標籤/搜索