一、sed 概述
- sed 是一個流編輯器,用於在輸入流(文件或管道中的輸入)上執行基本文本轉換。
- sed 能夠對文本文件進行增刪改查等操作。
- sed 擁有兩個緩衝區,活躍模式空間(active pattern space)與輔助保持空間(auxiliary hold space), 簡稱爲活躍區和暫存區,且這兩個緩衝區默認都爲空。
- sed 的基本操作只需要用到活躍區,sed的高級操作需要活躍區與暫存區的相互配合。
- 在 sed 的基本操作中,sed 從輸入流中得到當前處理的行,會先刪除結尾的換行符,存儲在一個臨時緩衝區,即活躍區;然後 sed 會在活躍區中處理文本,處理完成後加上換行符,並且傳送到 stdout (如果沒有-n選項),再接着處理下一行,如此循環往復,直至文件末尾,這就是 sed 的基本工作原理。由此可見,sed 在默認情況下是不修改原文件的。
- 除非使用特殊命令 (如 “D”), 否則活躍區的數據將在兩個週期之間被刪除。
- 在 sed 的高級操作中,多了一個暫存區,暫存區是與活躍區進行交互的,且以活躍區爲主,暫存區爲輔,sed 匹配的內容最終都得經由活躍區傳輸至 stdout 。
- 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
- -n 靜默模式,禁止自動打印到標準輸出
- -e script 可以多次使用-e,將命令加入命令集。在活躍區,命令集會運行處理輸入
sed -n -e '1,3p' -e '2,4p' nums.txt
- -f script-file 將命令寫入文件,使用-f,加入命令集
- -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
- -E -r 使用拓展正則
- -z 和grep -Z類似,常用來處理文件名帶空格的文件
三、 sed 腳本
sed 腳本命令的語法爲
[addr]X[options]
X是sed單字符的命令;addr是可選的行地址,如果指定,則在匹配的行執行命令X;options是一些sed命令需要的參數。
- 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 addr1和addr2可以是正則表達式和數字。如果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
- $ 最後一行
- 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 全局替換
- number 第number次匹配才替換
- 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'
- a text 在行下方添加文本
參考鏈接: