外置命令。
[root@localhost ~]# sed [選項] [腳本命令] 文件名
- sed 命令的選項
| 選項 | 功能 |
|---|---|
| -e 腳本命令 | 該選項會將其后跟的腳本命令添加到已有的命令中 |
| -f 腳本命令文件 | 該選項會將其后文件中的腳本命令添加到已有的命令中 |
| -n | 默認情況下,sed 會在所有的腳本指定執(zhí)行完畢后,會自動輸出處理后的內(nèi)容,而該選項會屏蔽啟動輸出,需使用 print 命令來完成輸出 |
| -i | 此選項會直接修改源文件,要慎用 |
sed 命令的執(zhí)行順序:
- 每次僅讀取一行內(nèi)容;
- 根據(jù)提供的規(guī)則命令匹配并修改數(shù)據(jù)。注意,sed 默認不會直接修改源文件數(shù)據(jù),而是會將數(shù)據(jù)復(fù)制到緩沖區(qū)中,修改也僅限于緩沖區(qū)中的數(shù)據(jù);
- 將執(zhí)行結(jié)果輸出。
當(dāng)一行數(shù)據(jù)匹配完成后,它會繼續(xù)讀取下一行數(shù)據(jù),并重復(fù)這個過程,直到將文件中所有數(shù)據(jù)處理完畢。
1. sed 腳本命令
1.1 sed s 替換單詞腳本命令
[address]s/pattern/replacement/flags
address 表示指定要操作的具體行,pattern 指的是需要替換的內(nèi)容,replacement 指的是要替換的新內(nèi)容。
- sed s 命令 flags 標(biāo)記及功能
| flags 標(biāo)記 | 功能 |
|---|---|
| n | 1~512 之間的數(shù)字,表示指定要替換的字符串出現(xiàn)第幾次時才進行替換,例如,一行中有 3 個 A,但用戶只想替換第二個 A,這是就用到這個標(biāo)記 |
| g | 對數(shù)據(jù)中所有匹配到的內(nèi)容進行替換,如果沒有 g,則只會在第一次匹配成功時做替換操作。例如,一行數(shù)據(jù)中有 3 個 A,則只會替換第一個 A |
| p | 會打印與替換命令中指定的模式匹配的行。此標(biāo)記通常與 -n 選項一起使用 |
| w file | 將緩沖區(qū)中的內(nèi)容寫到指定的 file 文件中 |
| & | 用正則表達式匹配的內(nèi)容進行替換 |
| \n | 匹配第 n 個子串,該子串之前在 pattern 中用 () 指定 |
| \ | 轉(zhuǎn)義(轉(zhuǎn)義替換部分包含:&、\ 等) |
- 示例
[root@localhost ~]# sed 's/test/trial/2' data4.txt
This is a test of the trial script.
This is the second test of the trial script.
# 可以看到,使用數(shù)字 2 作為標(biāo)記的結(jié)果就是,sed 編輯器只替換每行中第 2 次
# 出現(xiàn)的匹配模式
[root@localhost ~]# sed 's/test/trial/g' data4.txt
This is a trial of the trial script.
This is the second trial of the trial script.
# 用新文件替換所有匹配的字符串,可以使用 g 標(biāo)記
[root@localhost ~]# sed -n 's/test/trial/p' data5.txt
This is a trial line.
# -n 選項會禁止 sed 輸出,但 p 標(biāo)記會輸出修改過的行,將二者匹配使用的效果
# 就是只輸出被替換命令修改過的行
[root@localhost ~]# sed 's/test/trial/w test.txt' data5.txt
This is a trial line.
This is a different line.
# w 標(biāo)記會將匹配后的結(jié)果保存到指定文件中
[root@localhost ~]# sed 's/\/bin\/bash/\/bin\/csh/' /etc/passwd
# 在使用 s 腳本命令時,替換類似文件路徑的字符串會比較麻煩,需要將路徑中的
# 正斜線進行轉(zhuǎn)義
1.2 sed d 刪除行腳本命令
[address]d
如果需要刪除文本中的特定行,可以用 d 腳本命令,它會刪除指定行中的所有內(nèi)容。但使用該命令時要特別小心,如果你忘記指定具體行的話,文件中的所有內(nèi)容都會被刪除。
在默認情況下 sed 并不會修改原始文件,這里被刪除的行只是從 sed 的輸出中消失了,原始文件沒做任何改變。
- 示例
[root@localhost ~]# sed 'd' data1.txt
# 全部刪除
[root@localhost ~]# sed '3d' data6.txt
This is line number 1.
This is line number 2.
This is line number 4.
# 刪除 data6.txt 文件內(nèi)容中的第 3 行
[root@localhost ~]# sed '2,3d' data6.txt
This is line number 1.
This is line number 4.
# 刪除 data6.txt 文件內(nèi)容中的第 2、3行
[root@localhost ~]#sed '/1/,/3/d' data6.txt
This is line number 4.
# 刪除第 1~3 行的文本數(shù)據(jù)
[root@localhost ~]# sed '3,$d' data6.txt
This is line number 1.
This is line number 2.
# 刪除 data6.txt 文件內(nèi)容中第 3 行開始的所有的內(nèi)容
1.3 sed a 和 i 插入行腳本命令
a 命令表示在指定行的后面附加一行,i 命令表示在指定行的前面插入一行,它們的基本格式完全相同。
[address]a(或 i)\新文本內(nèi)容
- 示例
[root@localhost ~]# sed '3i\
>This is an inserted line.' data6.txt
This is line number 1.
This is line number 2.
This is an inserted line.
This is line number 3.
# 將一個新行插入到數(shù)據(jù)流第三行前
[root@localhost ~]# sed '3a\
>This is an appended line.' data6.txt
This is line number 1.
This is line number 2.
This is line number 3.
This is an appended line.
This is line number 4.
# 將一個新行附加到數(shù)據(jù)流中第三行后
[root@localhost ~]# sed '1i\
>This is one line of new text.\
>This is another line of new text.' data6.txt
This is one line of new text.
This is another line of new text.
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
# 將一個多行數(shù)據(jù)添加到數(shù)據(jù)流中,只需對要插入或附加的文本中的每一行
# 末尾(除最后一行)添加反斜線即可
1.4 sed c 替換行腳本命令
c 命令表示將指定行中的所有內(nèi)容,替換成該選項后面的字符串。
[address]c\用于替換的新文本
- 示例
[root@localhost ~]# sed '3c\
>This is a changed line of text.' data6.txt
This is line number 1.
This is line number 2.
This is a changed line of text.
This is line number 4.
# sed 編輯器會修改第三行中的文本
1.5 sed y 轉(zhuǎn)換字母腳本命令
y 轉(zhuǎn)換命令是唯一可以處理單個字符的 sed 腳本命令。轉(zhuǎn)換命令是一個全局命令,也就是說,它會文本行中找到的所有指定字符自動進行轉(zhuǎn)換,而不會考慮它們出現(xiàn)的位置。
[address]y/inchars/outchars/
轉(zhuǎn)換命令會對 inchars 和 outchars 值進行一對一的映射,即 inchars 中的第一個字符會被轉(zhuǎn)換為 outchars 中的第一個字符,第二個字符會被轉(zhuǎn)換成 outchars 中的第二個字符...這個映射過程會一直持續(xù)到處理完指定字符。如果 inchars 和 outchars 的長度不同,則 sed 會產(chǎn)生一條錯誤消息。
- 示例
[root@localhost ~]# sed 'y/123/789/' data8.txt
This is line number 7.
This is line number 8.
This is line number 9.
This is line number 4.
This is line number 7 again.
This is yet another line.
This is the last line in the file.
# inchars 模式中指定字符的每個實例都會被替換成 outchars 模式中相
# 同位置的那個字符
1.6 sed p 打印行腳本命令
p 命令表示搜索符號條件的行,并輸出該行的內(nèi)容。p 命令常見的用法是打印包含匹配文本模式的行。
[address]p
- 示例
[root@localhost ~]# sed -n '/number 3/p' data6.txt
This is line number 3.
# 用 -n 選項和 p 命令配合使用,我們可以禁止輸出其他行,只打印包含
# 匹配文本模式的行
[root@localhost ~]# sed -n '/3/{
>p
>s/line/test/p
>}' data6.txt
This is line number 3.
This is test number 3.
# sed 命令會查找包含數(shù)字 3 的行,然后執(zhí)行兩條命令。首先,腳本用 p 命
# 令來打印出原始行;然后它用 s 命令替換文本,并用 p 標(biāo)記打印出替換結(jié)
# 果。輸出同時顯示了原來的行文本和新的行文本
1.7 sed w 寫入行腳本命令
w 命令用來將文本中指定行的內(nèi)容寫入文件中。通過使用 w 腳本命令,sed 可以實現(xiàn)將包含文本模式的數(shù)據(jù)行寫入目標(biāo)文件。
[address]w filename
這里的 filename 表示文件名,可以使用相對路徑或絕對路徑,但不管是哪種,運行 sed 命令的用戶都必須有文件的寫權(quán)限。
- 示例
[root@localhost ~]# sed '1,2w test.txt' data6.txt
# 將數(shù)據(jù)流data6.txt中的前兩行打印到一個文本文件test.txt中
[root@localhost ~]# cat data11.txt
Blum, R Browncoat
McGuiness, A Alliance
Bresnahan, C Browncoat
Harken, C Alliance
[root@localhost ~]# sed -n '/Browncoat/w Browncoats.txt' data11.txt
[root@localhost ~]# cat Browncoats.txt
Blum, R Browncoat
Bresnahan, C Browncoat
# 將數(shù)據(jù)流data11.txt中符合 Browncoat 行打印到一個文本文
# 件Browncoats.txt中
1.8 sed r 插入全文件腳本命令
r 命令用于將一個獨立文件的數(shù)據(jù)插入到當(dāng)前數(shù)據(jù)流的指定位置。
[address]r filename
- 示例
[root@localhost ~]# cat data12.txt
This is an added line.
This is the second added line.
[root@localhost ~]# sed '3r data12.txt' data6.txt
This is line number 1.
This is line number 2.
This is line number 3.
This is an added line.
This is the second added line.
This is line number 4.
# 會將data12.txt文件中的內(nèi)容插入到data6.txt中第3行的后面
[root@localhost ~]# sed '$r data12.txt' data6.txt
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
This is an added line.
This is the second added line.
# 會將data12.txt文件中的內(nèi)容插入到data6.txt中末尾,想將指定文件
# 中的數(shù)據(jù)插入到數(shù)據(jù)流的末尾,可以使用 $ 地址符
1.9 sed q 退出腳本命令
q 命令的作用是使 sed 命令在第一次匹配任務(wù)結(jié)束后,退出 sed 程序,不再進行對后續(xù)數(shù)據(jù)的處理。
- 示例
[root@localhost ~]# sed '2q' test.txt
This is line number 1.
This is line number 2.
# 在打印輸出第 2 行之后,就停止了,是 q 命令造成的
[root@localhost ~]# sed '/number 1/{ s/number 1/number 0/;q; }' test.txt
This is line number 0.
# 使用 q 命令之后,sed 命令會在匹配到 number 1 時,將其替換
# 成 number 0,然后直接退出
2. sed 腳本命令的尋址方式
對各個腳本命令來說,address 用來表明該腳本命令作用到文本中的具體行。
默認情況下,sed 命令會作用于文本數(shù)據(jù)的所有行。如果只想將命令作用于特定行或某些行,則必須寫明 address 部分,表示的方法有以下 2 種:
- 以數(shù)字形式指定行區(qū)間。
- 用文本模式指定具體行區(qū)間。
以上兩種形式都可以使用如下這 2 種格式:
[address]腳本命令
或者
address {
多個腳本命令
}
2.1 以數(shù)字形式指定行區(qū)間
當(dāng)使用數(shù)字方式的行尋址時,可以用行在文本流中的行位置來引用。sed 會將文本流中的第一行編號為 1,然后繼續(xù)按順序為接下來的行分配行號。在腳本命令中,指定的地址可以是單個行號,或是用起始行號、逗號以及結(jié)尾行號指定的一定區(qū)間范圍內(nèi)的行。
- 示例
[root@localhost ~]#sed '2s/dog/cat/' data1.txt
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
# 只修改地址指定的第二行的文本
[root@localhost ~]# sed '2,3s/dog/cat/' data1.txt
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy dog
# 只修改地址指定的第二行到第三行的文本
[root@localhost ~]# sed '2,$s/dog/cat/' data1.txt
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy cat
# 將命令作用到文本中從第二行開始的所有行,可以用特殊地
# 址——美元符($)表示末尾
2.2 用文本模式指定行區(qū)間
允許指定文本模式來過濾出命令要作用的行
/pattern/command
注意,必須用正斜線將要指定的 pattern 封起來,sed 會將該命令作用到包含指定文本模式的行上。
- 示例
[root@localhost ~]# grep demo /etc/passwd
demo:x:502:502::/home/Samantha:/bin/bash
[root@localhost ~]# sed '/demo/s/bash/csh/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
...
demo:x:502:502::/home/demo:/bin/csh
...
# 只修改用戶 demo 的默認 shell 的 bash 變成 csh
3. sed 多行命令
sed 包含了三個可用來處理多行文本的特殊命令,分別是:
- Next 命令(N):將數(shù)據(jù)流中的下一行加進來創(chuàng)建一個多行組來處理。
- Delete(D):刪除多行組中的一行。
- Print(P):打印多行組中的一行。
注意,以上命令的縮寫,都為大寫。
3.1 N 多行操作命令
N 命令會將下一行文本內(nèi)容添加到緩沖區(qū)已有數(shù)據(jù)之后(之間用換行符分隔),從而使前后兩個文本行同時位于緩沖區(qū)中,sed 命令會將這兩行數(shù)據(jù)當(dāng)成一行來處理。
- 示例
[root@localhost ~]# sed '/first/{ N ; s/\n/ / }' data2.txt
This is the header line.
This is the first data line. This is the second data line.
This is the last line.
# 查找含有單詞 first 的那行文本。文本文件中的兩行在 sed 的
# 輸出中成了一行
[root@localhost ~]# sed 'N ; s/System Administrator/Desktop User/' data3.txt
On Tuesday, the Linux Desktop User's group meeting will be held.
All Desktop Users should attend.
Thank you for your attendance.
# 用 N 命令將發(fā)現(xiàn)第一個單詞的那行和下一行合并后,即使短語內(nèi)出現(xiàn)了換行,
# 你仍然可以找到它,這是因為,替換命令在 System 和 Administrator之間
# 用了通配符(.)來匹配空格和換行符這兩種情況。但當(dāng)它匹配了換行符時,
# 它就從字符串中刪掉了換行符,導(dǎo)致兩行合并成一行
[root@localhost ~]# sed '
> s/System\nAdministrator/Desktop\nUser/
> N
> s/System Administrator/Desktop User/
> ' data3.txt
On Tuesday, the Linux Desktop
User's group meeting will be held.
All Desktop Users should attend.
Thank you for your attendance.
# 查找單行中短語的替換命令在數(shù)據(jù)流的最后一行也能正常工作,多行替換命令
# 則會負責(zé)短語出現(xiàn)在數(shù)據(jù)流中間的情況
3.2 D 多行刪除命令
sed 不僅提供了單行刪除命令(d),也提供了多行刪除命令 D,其作用是只刪除緩沖區(qū)中的第一行,也就是說,D 命令將緩沖區(qū)中第一個換行符(包括換行符)之前的內(nèi)容刪除掉。
- 示例
On Tuesday, the Linux System
Administrator's group meeting will be held.
All System Administrators should attend.
[root@localhost ~]# sed 'N ; /System\nAdministrator/D' data4.txt
Administrator's group meeting will be held.
All System Administrators should attend.
# 文本的第二行被 N 命令加到了緩沖區(qū),因此 sed 命令第一次匹配就是成功,
# 而 D 命令會將緩沖區(qū)中,第一個換行符之前(也就是第一行)的數(shù)據(jù)刪除,
# 所以,得到了如上所示的結(jié)果
# 程序中空白行
This is the header line.
This is a data line.
# 程序中空白行
This is the last line.
[root@localhost ~]# sed '/^$/{N ; /header/D}' data5.txt
This is the header line.
This is a data line.
# 程序中空白行
This is the last line.
# sed會查找空白行,然后用 N 命令來將下一文本行添加到緩沖區(qū)。此時如果緩沖
# 區(qū)的內(nèi)容中含有單詞header,則 D 命令會刪除緩沖區(qū)中的第一行
3.3 P 多行打印命令
同 d 和 D 之間的區(qū)別一樣,P(大寫)命令和單行打印命令 p(小寫)不同,對于具有多行數(shù)據(jù)的緩沖區(qū)來說,它只會打印緩沖區(qū)中的第一行,也就是首個換行符之前的所有內(nèi)容。
- 示例
[root@localhost ~]# sed '/.*/N;P'
aaa
aaa
bbb
ccc
ccc
ddd
eee
eee
fff
# 每次都使用 N 將下一行內(nèi)容追加到緩沖區(qū)內(nèi)容的后面(用換行符間隔),也就是
# 說,第一次時緩沖區(qū)中的內(nèi)容為 aaa\nbbb,但 P(大寫) 命令的作用的打印換
# 行符之前的內(nèi)容,也就是 aaa,之后則是 sed 在自動輸出功能輸出 aaa 和 bbb
# (sed 命令會自動將 \n 輸出為換行),依次類推,就輸出了所看到的結(jié)果
[root@localhost ~]# sed '/.*/N;p'
aaa
bbb
aaa
bbb
ccc
ddd
ccc
ddd
eee
fff
eee
fff
# 使用的是 p (小寫)單行打印命令,它會將緩沖區(qū)中的所有內(nèi)容全部打印出
# 來(\n 會自動輸出為換行),因此,出現(xiàn)了看到的結(jié)果
4. sed 保持空間
sed 命令處理的是緩沖區(qū)中的內(nèi)容,其實這里的緩沖區(qū),應(yīng)稱為模式空間。值得一提的是,模式空間并不是 sed 命令保存文件的唯一空間。sed 還有另一塊稱為保持空間的緩沖區(qū)域,它可以用來臨時存儲一些數(shù)據(jù)。sed 操作保持空間的命令:
| 命令 | 功能 |
|---|---|
| h | 將模式空間中的內(nèi)容復(fù)制到保持空間 |
| H | 將模式空間中的內(nèi)容附加到保持空間 |
| g | 將保持空間中的內(nèi)容復(fù)制到模式空間 |
| G | 將保持空間中的內(nèi)容附加到模式空間 |
| x | 交換模式空間和保持空間中的內(nèi)容 |
- 示例
[root@localhost ~]# cat data2.txt
This is the header line.
This is the first data line.
This is the second data line.
This is the last line.
[root@localhost ~]# sed -n '/first/ {h ; p ; n ; p ; g ; p }' data2.txt
This is the first data line.
This is the second data line.
This is the first data line.
這個例子的運行過程是這樣的:
- sed腳本命令用正則表達式過濾出含有單詞first的行。
- 當(dāng)含有單詞 first 的行出現(xiàn)時,h 命令將該行放到保持空間。
- p 命令打印模式空間也就是第一個數(shù)據(jù)行的內(nèi)容。
- n 命令提取數(shù)據(jù)流中的下一行(This is the second data line),并將它放到模式空間。
- p 命令打印模式空間的內(nèi)容,現(xiàn)在是第二個數(shù)據(jù)行。
- g 命令將保持空間的內(nèi)容(This is the first data line)放回模式空間,替換當(dāng)前文本。
- p 命令打印模式空間的當(dāng)前內(nèi)容,現(xiàn)在變回第一個數(shù)據(jù)行了。
5. sed 改變指定流程
5.1 b 分支命令
通常,sed 程序的執(zhí)行過程會從第一個腳本命令開始,一直執(zhí)行到最后一個腳本命令(D 命令是個例外,它會強制 sed 返回到腳本的頂部,而不讀取新的行)。sed 提供了 b 分支命令來改變命令腳本的執(zhí)行流程,其結(jié)果與結(jié)構(gòu)化編程類似。
[address]b [label]
其中,address 參數(shù)決定了哪些行的數(shù)據(jù)會觸發(fā)分支命令,label 參數(shù)定義了要跳轉(zhuǎn)到的位置。如果沒有加 label 參數(shù),跳轉(zhuǎn)命令會跳轉(zhuǎn)到腳本的結(jié)尾。
- 示例
[root@localhost ~]# cat data2.txt
This is the header line.
This is the first data line.
This is the second data line.
This is the last line.
[root@localhost ~]# sed '{2,3b ; s/This is/Is this/ ; s/line./test?/}' data2.txt
Is this the header test?
This is the first data line.
This is the second data line.
Is this the last test?
# 因為 b 命令未指定 label 參數(shù),因此數(shù)據(jù)流中的第2行和第3行并
# 沒有執(zhí)行那兩個替換命令
[root@localhost ~]# sed '{/first/b jump1 ; s/This is the/No jump on/
> :jump1
> s/This is the/Jump here on/}' data2.txt
No jump on header line
Jump here on first data line
No jump on second data line
No jump on last line
# 如果文本行中出現(xiàn)了 first,程序的執(zhí)行會直接跳到 jump1 標(biāo)簽之后的
# 腳本行。如果分支命令的模式?jīng)]有匹配,sed 會繼續(xù)執(zhí)行所有的腳本命令
[root@localhost ~]# echo "This, is, a, test, to, remove, commas." | sed -n '{
> :start
> s/,//1p
> /,/b start
> }'
This is, a, test, to, remove, commas.
This is a, test, to, remove, commas.
This is a test, to, remove, commas.
This is a test to, remove, commas.
This is a test to remove, commas.
This is a test to remove commas.
# 當(dāng)緩沖區(qū)中的行內(nèi)容中有逗號時,腳本命令就會一直循環(huán)執(zhí)行,每次迭代都
# 會刪除文本中的第一個逗號,并打印字符串,直至內(nèi)容中沒有逗號
5.2 t 測試命令
類似于 b 分支命令,t 命令也可以用來改變 sed 腳本的執(zhí)行流程。t 測試命令會根據(jù) s 替換命令的結(jié)果,如果匹配并替換成功,則腳本的執(zhí)行會跳轉(zhuǎn)到指定的標(biāo)簽;反之,t 命令無效。在沒有指定標(biāo)簽的情況下,如果 s 命令替換成功,sed 會跳轉(zhuǎn)到腳本的結(jié)尾(相當(dāng)于不執(zhí)行任何腳本命令)。
[address]t [label]
- 示例
[root@localhost ~]# sed '{
> s/first/matched/
> t
> s/This is the/No match on/
> }' data2.txt
No match on header line
This is the matched data line
No match on second data line
No match on last line
# 第一個替換命令會查找模式文本 first,如果匹配并替換成功,命令會直接跳
# 過后面的替換命令;反之,如果第一個替換命令未能匹配成功,第二個替換命
# 令就會被執(zhí)行
[root@localhost ~]# echo "This, is, a, test, to, remove, commas. " | sed -n '{
> :start
> s/,//1p
> t start
> }'
This is, a, test, to, remove, commas.
This is a, test, to, remove, commas.
This is a test, to, remove, commas.
This is a test to, remove, commas.
This is a test to remove, commas.
This is a test to remove commas.