Linux 文本處理利器:sed 命令
sed 簡介
sed(Stream Editor)是一款非交互式的流編輯器,誕生于 1973–1974 年間的貝爾實驗室,由 McMahon 開發。它專為文本處理而生,功能強大,是 Linux 文本處理常客之一。
(另外兩名常客通常視為 grep命令和 awk命令)
其中,sed 與 awk 并稱 Linux/Unix 兩大文字處理王牌工具,sed 側重于替換,awk 側重于分割與重組。
本文將深入探討 sed 命令的使用方法與實用技巧。
sed 工作流程
sed 的工作流程可簡單概括為:
讀取行 → 執行 → 顯示 → 讀取行 → 執行 → 顯示 → ……(重復流程)
詳細步驟:
- 讀取行:從輸入流(文件、管道、標準輸入)讀取一行存入
pattern space
。 - 執行:按順序對當前行應用 sed 命令。
- 顯示:將處理后的數據發送到輸出流,并清空
pattern space
。 - 循環:重復上述過程直到所有輸入處理完畢。
注意事項:
pattern space
是內存中的臨時區域,關機或關閉終端后數據丟失。- 默認不修改源文件,除非使用
-i
選項。 hold space
是另一個內存區域,用于持久化存儲數據,供后續檢索使用。- 未指定輸入文件時,sed 從標準輸入讀取數據。
環境準備
[furongwang@shell ~]$ vim test
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/false
daemon:x:2:2:daemon:/sbin:/bin/false
mail:x:8:12:mail:/var/spool/mail:/bin/false
ftp:x:14:11:ftp:/home/ftp:/bin/false
&nobody:$:99:99:nobody:/:/bin/false
zhangy:x:1000:100:,,,:/home/zhangy:/bin/bash
http:x:33:33::/srv/http:/bin/false
dbus:x:81:81:System message bus:/:/bin/false
hal:x:82:82:HAL daemon:/:/bin/false
mysql:x:89:89::/var/lib/mysql:/bin/false
aaa:x:1001:1001::/home/aaa:/bin/bash
ba:x:1002:1002::/home/zhangy:/bin/bash
test:x:1003:1003::/home/test:/bin/bash
@zhangying:*:1004:1004::/home/test:/bin/bash
policykit:x:102:1005:Po
sed 命令語法
基本格式:
sed [option] [sed-command] [input-file]
常用選項:
選項 | 說明 |
---|---|
-n | 禁止自動打印模式空間 |
-e | 添加要執行的腳本 |
-f | 從文件中讀取腳本,腳本中的每一個 sed 命令獨自成一行 |
-i | 直接修改源文件(可指定備份后綴) |
-r | 使用擴展正則表達式 |
示例:
打印文件內容(模擬 cat):
sed '' data.txt(任意文件名)
[furongwang@shell ~]$ cat data.txt
I am studing sed
I am www.twle.cn
I am a no-work-men
I am so handsome[furongwang@shell ~]$ sed '' data.txt
I am studing sed
I am www.twle.cn
I am a no-work-men
I am so handsome
從標準輸入讀取:
sed ''# 輸入內容后按 Ctrl+D 結束
[furongwang@shell ~]$ sed ''
# 輸入hello world,并回車
hello world
# 輸出hello world
hello world
# 按ctrl+d推出
行尋址與模式尋址
行尋址語法:
[address1[,address2]]命令
示例:
# 打印第1行
[furongwang@shell ~]$ sed -n '1p' test# 打印第1到3行
[furongwang@shell ~]$ sed -n '1,3p' test# 打印第3行到最后
[furongwang@shell ~]$ sed -n '3,$p' test# 打印第2行及后面2行
[furongwang@shell ~]$ sed -n '2,+2p' test# 每隔2行打印一次
[furongwang@shell ~]$ sed -n '1~2p' test
模式尋址:
# 打印含 "zhang" 的行
[furongwang@shell ~]$ sed -n '/zhang/p' test# 打印從 root 開頭到 mail 開頭的行
[furongwang@shell ~]$ sed -n '/^root/,/^mail/p' test
常用子命令詳解
1. 打印(p / P)
p
:打印整個模式空間P
:打印模式空間的第一行
[furongwang@shell ~]$ sed -n '1p' test # 打印第1行
[furongwang@shell ~]$ sed -n '1,3p' test # 打印1~3行
2. 讀取下一行(n / N)
n
:讀取下一行覆蓋當前行N
:追加下一行到當前行(用\n
連接)
# 打印偶數行
[furongwang@shell ~]$ sed -n 'n;p' test# 合并相鄰兩行
[furongwang@shell ~]$ sed 'N;s/\n/==/' test
3. 替換(s)
# 替換每行第一個 root
[furongwang@shell ~]$ sed 's/root/tankzhang/' test# 替換所有 root
[furongwang@shell ~]$ sed 's/root/tankzhang/g' test# 替換每行第3個 my
[furongwang@shell ~]$ sed 's/my/your/3' test1.txt# 自定義分隔符
[furongwang@shell ~]$ sed 's#root#hello#' test
4. 插入與追加(i / a)
# 在匹配行上方插入
[furongwang@shell ~]$ sed '/root/i====aaaa====' test# 在匹配行下方追加
[furongwang@shell ~]$ sed '/root/a====iiii====' test
5. 刪除(d / D)
d
:刪除整個模式空間D
:刪除模式空間的第一行
# 刪除1~14行
[furongwang@shell ~]$ sed '1,14d' test# 刪除含 false 或 bash 的行
[furongwang@shell ~]$ sed '/\(false\|bash\)/d' test
6. 寫文件(w / W)
# 將 root 開頭的行寫入文件
[furongwang@shell ~]$ sed -n '/^root/w output.txt' test
[furongwang@shell ~]$ cat output.txt
root:x:0:0:root:/root:/bin/bash# 小寫w寫入
[furongwang@shell ~]$ vim scripts
1{
N
w write.log
}
[furongwang@shell ~]$ sed -n -f scripts test# 小寫w寫入包含模式中所有行
[furongwang@shell ~]$ cat write.log
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/bin/false# 大寫W寫入只包含模式中第一行
[furongwang@shell ~]$ vim scripts
1{
N
W write.log
}
[furongwang@shell ~]$ sed -n -f scripts test
[furongwang@shell ~]$ cat write.log
root:x:0:0:root:/root:/bin/bash
7. 退出(q)
# 處理到第3行退出
[furongwang@shell ~]$ sed '3q' test
8. 取反(!)
# 打印非 root 開頭的行
[furongwang@shell ~]$ sed -n '/^root/!p' test
高級用法
多命令執行:
# 使用分號分隔
[furongwang@shell ~]$ sed '1d;2d;5d' test# 使用 -e 選項
[furongwang@shell ~]$ sed -e '1d' -e '2d' test# 使用腳本文件
[furongwang@shell ~]$ sed -f script.sed test
正則表達式與子串:
# 使用轉義括號
[furongwang@shell ~]$ sed 's/\(root\)/\1user/g' test# 使用 -r 避免轉義
[furongwang@shell ~]$ sed -r 's/(root)/\1user/g' test# 使用 & 代表匹配內容
[furongwang@shell ~]$ sed 's/root/&user/g' test
模式空間與保持空間(g/G/h/H):
命令 | 說明 |
---|---|
g | 用保持空間內容覆蓋模式空間 |
G | 將保持空間內容追加到模式空間 |
h | 用模式空間內容覆蓋保持空間 |
H | 將模式空間內容追加到保持空間 |
# 每行后加空行
[furongwang@shell ~]$ sed 'G' test# 復制匹配行到文件末尾
[furongwang@shell ~]$ sed -e '/root/h' -e '$G' test
附:sed 命令完整幫助信息
[furongwang@shell ~]$ sed --help
Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]...-n, --quiet, --silentsuppress automatic printing of pattern space-e script, --expression=scriptadd the script to the commands to be executed-f script-file, --file=script-fileadd the contents of script-file to the commands to be executed--follow-symlinksfollow symlinks when processing in place-i[SUFFIX], --in-place[=SUFFIX]edit files in place (makes backup if SUFFIX supplied)-c, --copyuse copy instead of rename when shuffling files in -i mode-b, --binarydoes nothing; for compatibility with WIN32/CYGWIN/MSDOS/EMX (open files in binary mode (CR+LFs are not treated specially))-l N, --line-length=Nspecify the desired line-wrap length for the `l' command--posixdisable all GNU extensions.-r, --regexp-extendeduse extended regular expressions in the script.-s, --separateconsider files as separate rather than as a single continuouslong stream.-u, --unspaceedload minimal amounts of data from the input files and flushthe output spaces more often-z, --null-dataseparate lines by NUL characters--helpdisplay this help and exit--versionoutput version information and exitIf no -e, --expression, -f, or --file option is given, then the first
non-option argument is taken as the sed script to interpret. All
remaining arguments are names of input files; if no input files are
specified, then the standard input is read.GNU sed home page: <http://www.gnu.org/software/sed/>.
General help using GNU software: <http://www.gnu.org/gethelp/>.
E-mail bug reports to: <bug-sed@gnu.org>.
Be sure to include the word ``sed'' somewhere in the ``Subject:'' field.
-n, --quiet, --silent 取消自動打印模式空間-e 腳本, --expression=腳本 添加“腳本”到程序的運行列表-f 腳本文件, --file=腳本文件 添加“腳本文件”到程序的運行列表--follow-symlinks 直接修改文件時跟隨軟鏈接-i[擴展名], --in-place[=擴展名] 直接修改文件(如果指定擴展名就備份文件)-l N, --line-length=N 指定“l”命令的換行期望長度--posix 關閉所有 GNU 擴展-r, --regexp-extended 在腳本中使用擴展正則表達式-s, --separate 將輸入文件視為各個獨立的文件而不是一個長的連續輸入-u, --unspaceed 從輸入文件讀取最少的數據,更頻繁的刷新輸出--help 打印幫助并退出--version 輸出版本信息并退出-a ∶新增, a 的后面可以接字串,而這些字串會在新的一行出現(目前的下一行)~-c ∶取代, c 的后面可以接字串,這些字串可以取代 n1,n2 之間的行!-d ∶刪除,因為是刪除啊,所以 d 后面通常不接任何咚咚;-i ∶插入, i 的后面可以接字串,而這些字串會在新的一行出現(目前的上一行);-p ∶列印,亦即將某個選擇的資料印出。通常 p 會與參數 sed -n 一起運作~-s ∶取代,可以直接進行取代的工作哩!通常這個 s 的動作可以搭配正規表示法