Linux shell文本三劍客之sed的使用

一、sed 概述

  1. sed 是一個流編輯器,用於在輸入流(文件或管道中的輸入)上執行基本文本轉換。
  2. sed 能夠對文本文件進行增刪改查等操作。
  3. sed 擁有兩個緩衝區,活躍模式空間(active pattern space)與輔助保持空間(auxiliary hold space), 簡稱爲活躍區和暫存區,且這兩個緩衝區默認都爲空。
  4. sed 的基本操作只需要用到活躍區,sed的高級操作需要活躍區與暫存區的相互配合。
  5. 在 sed 的基本操作中,sed 從輸入流中得到當前處理的行,會先刪除結尾的換行符,存儲在一個臨時緩衝區,即活躍區;然後 sed 會在活躍區中處理文本,處理完成後加上換行符,並且傳送到 stdout (如果沒有-n選項),再接着處理下一行,如此循環往復,直至文件末尾,這就是 sed 的基本工作原理。由此可見,sed 在默認情況下是不修改原文件的。
  6. 除非使用特殊命令 (如 “D”), 否則活躍區的數據將在兩個週期之間被刪除。
  7. 在 sed 的高級操作中,多了一個暫存區,暫存區是與活躍區進行交互的,且以活躍區爲主,暫存區爲輔,sed 匹配的內容最終都得經由活躍區傳輸至 stdout 。
  8. sed 的完整語法是

    sed OPTIONS… [SCRIPT] [INPUTFILE…]

二、sed 命令行參數

# 測試數據
# 生成1到100
seq 1 100 > nums.txt
cat>words.txt<<-EOF
hello world
Common methods to solve matrix related problem include DFS, BFS, dynamic programming, etc.
hello123 world123
-hello-
_hello_
EOF
# 生成ASCII表中A到z,包含A-Za-z
printf "%s\n" {A..z} > chars.txt

cat>command.txt<<-EOF
pwd
echo "hello world"
EOF

  1. -n 靜默模式,禁止自動打印到標準輸出
  2. -e script 可以多次使用-e,將命令加入命令集。在活躍區,命令集會運行處理輸入
    sed -n -e '1,3p' -e '2,4p' nums.txt
    
  3. -f script-file 將命令寫入文件,使用-f,加入命令集
  4. -i[SUFFIX] 原地編輯文件
    • GUN sed會輸出內容發送到臨時文件,而不是發送到標準輸出,當處理完輸入文件後,臨時文件會重命名爲輸入文件的名字
    • 如果提供SUFFIX,那就會在重命名前,將輸入文件重命名作爲備份。
    • -i後不能有其他短選項,因爲如果有會被當做SUFFIX
      # 這樣會出現問題,生成nums.txtn的備份文件,而-n也沒有生效
      sed -in '1,3p' nums.txt
      # 可以改成這樣
      sed -ni '1,3p' nums.txt
      # 或
      sed -n -i '1,3p' nums.txt
      # 或 將名字備份爲nums.txt.bak
      sed -n -i.bak '1,3p' nums.txt
      
  5. -E -r 使用拓展正則
  6. -z 和grep -Z類似,常用來處理文件名帶空格的文件

三、 sed 腳本

sed 腳本命令的語法爲

[addr]X[options]

X是sed單字符的命令;addr是可選的行地址,如果指定,則在匹配的行執行命令X;options是一些sed命令需要的參數。

  1. addr (沒有addr就默認是所有行)
    • $ 最後一行
      sed -n '$p' nums.txt
      
    • first~step 首行與步進,例如 1~2 就是奇數行, 2~2就是偶數行, 3~3就是3,6,9…
      sed -n '1~2p' nums.txt
      
    • addr1, addr2 addr1addr2可以是正則表達式和數字。如果addr2是正則,那麼檢查結束行是從addr1匹配的行後開始,範圍至少兩行(輸入流結束除外)
      sed -n '1,3p' nums.txt
      sed -n '2,/1/p' nums.txt
      # 至少兩行
      sed -n '2,/[0-9]/p' nums.txt
      
    • /regexp/ 所有匹配正則的行
      sed -n '/1/p' nums.txt
      
    • 0,/regexp/ 沒有第0行,地址0只是爲了處理在addr2與輸入第1行匹配的情況,其他與1,/regexp/相同
      sed -n '0,/1/p' nums.txt
      sed -n '1,/1/p' nums.txt
      
    • addr1,+N 匹配addr1,然後N
      sed -n '1,+5p' nums.txt
      # 所有匹配1的行加上後5行
      sed -n '/1/,+5p' nums.txt
      
    • addr1,~N 匹配addr1,然後到N的倍數行
      sed -n '/1/,~4p' nums.txt
      
    • ! 在上面的地址後加一個!,表示相反匹配
      sed -n '/1/,~4!p' nums.txt
      
  2. X
    • a text 在行下方添加文本
      sed '1a hello\nworld' nums.txt 
      
    • b label 無條件調到label
    • c text 替換行文本
      sed '1c hello\nworld' nums.txt 
      
    • d 刪除活躍區內容,立即開始下個循環
      sed '1,3d' nums.txt 
      
    • D 如果活躍區包含換行符,則刪除第一行,包含換行符。如果不包含換行符,則和d一樣
      sed 'N;$!D' nums.txt
      
    • e 執行在活躍區的shell命令
      sed 'e' command.txt 
      
    • e command 執行command
      # 使用e pwd可以在每行前輸出前執行命令
      sed 'e pwd' command.txt
      
    • F 打印當前輸入文件的名字
      sed 'F' nums.txt command.txt 
      
    • g 將活躍區內容替換爲緩存區內容
    • G 將活躍區內容加上換行符,然後將暫存區內容追加到活躍區
    • h 將暫存區內容替換爲活躍區內容
    • H 將暫存區內容加上換行符,然後將活躍區內容追加到暫存區
    • i text 在行的上方添加文本
      sed '1,3i hello\nworld' nums.txt 
      
    • n 跳過行
      # 兩個n跳過2行,每3行執行p
      sed -n 'n;n;p;' nums.txt
      
    • N 向活躍區添加換行符,接着再把下一行加進去。
      sed 'e echo ---' nums.txt
      sed 'N;e echo ---' nums.txt
      sed 'N;N;e echo ---' nums.txt
      
    • p 打印活躍區內容
      sed -n '1,10p' nums.txt 
      
    • P 打印活躍區的第一行
      # 每兩行打印第一行
      sed -n 'N;P' nums.txt
      
    • q[exit-code] 退出sed
      # 到第2行退出sed
      sed '2q10' nums.txt
      echo $?
      
    • r filename 讀文件
      # 每行都會讀command.txt,並默認打印出來
      sed 'r command.txt' nums.txt
      
    • s/regexp/replacement/[flags] 替換字符
      • g 全局替換
      • numbernumber次匹配才替換
      • p 如果進行了替換,則打印活躍區內容
      • w filename 如果進行了替換,則將結果寫入filename
      sed 's/1/a/' nums.txt
      sed 's/1/a/2' nums.txt
      sed -n 's/1/a/p' nums.txt
      sed -n 's/1/a/2p' nums.txt
      
    • w filename 將活躍區內容寫入文件
      sed -n 'w file.txt' nums.txt
      
    • x 交換活躍區與暫存區內容
    • y/src/dst/ 將活躍區的內容,按照匹配src的字符轉化dst相同位置的字符
      sed 'y/123/abc/' nums.txt
      
    • z 清空活躍區內容
    • # 註釋,直到下一行
    • { cmd ; cmd … } 命令組
      sed -n '1p;2p;100p' nums.txt
      sed -n '1{s/1/a/;p}' nums.txt
      
    • = 打印當前輸入行數
      sed -n '=' nums.txt
      
    • : label 給分支命令(b, t, T)指定label位置
      # 定義標籤t;使用N輸入兩行;將\n替換爲,;使用b跳到標籤t循環
      # 將所有換行替換爲,
      sed ':t;N;s/\n/,/;b t'
      

參考鏈接:

  1. http://blog.51cto.com/liansir/1836673
  2. http://www.gnu.org/software/sed/manual/sed.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章