學(xué)習(xí)使用 Sed 文本編輯器
Sed 缺少通常的文本框,而是按照用戶的命令直接寫入到文件上。
sed
命令是為 AT&T 最初的 Unix 操作系統(tǒng)第 7 版創(chuàng)建的,此后,可能每一個(gè) Unix 和 Linux 操作系統(tǒng)都包含了它。sed
應(yīng)用程序是一個(gè) 流編輯器,與文本編輯器不同的是,它不會(huì)打開一個(gè)視覺緩沖區(qū),將文件的數(shù)據(jù)加載到其中進(jìn)行處理。相反,它根據(jù)在終端輸入的命令或腳本中的一系列命令,逐行對(duì)文件進(jìn)行操作。
安裝
如果你使用的是 Linux、BSD 或 macOS,那么你已經(jīng)安裝了 GNU 或 BSD 版的 sed
。這是兩個(gè)不同的原始 sed
命令的重新實(shí)現(xiàn),雖然它們很相似,但也有一些小的區(qū)別。GNU sed
通常被認(rèn)為是功能最豐富的 sed
,而且它在這些平臺(tái)上都可以廣泛使用。
如果你找不到 GNU sed
(在非 Linux 系統(tǒng)上通常被稱為 gsed
),那么你可以從 GNU 網(wǎng)站上下載它的源代碼。安裝 GNU sed
的好處是,可以使用它的額外功能,但它也可以被限制為只符合 sed
的 POSIX 規(guī)范,如果你需要移植性的話。
在 Windows 上,你可以用 Chocolatey 來安裝 GNU sed
。
Sed 如何工作
sed
應(yīng)用程序一次只處理一行。因?yàn)樗鼪]有視覺顯示,所以它在內(nèi)存中創(chuàng)建了一個(gè)模式空間:一個(gè)包含輸入流的當(dāng)前行的空間(去掉任何尾部的換行符)。一旦填充了模式空間,你對(duì) sed
的指令就會(huì)被執(zhí)行。有時(shí)你的指令是有條件的,有時(shí)是無(wú)條件的,所以這些指令的結(jié)果取決于你如何使用 sed
。
當(dāng)命令結(jié)束時(shí),sed
會(huì)將模式空間的內(nèi)容打印到輸出流中。默認(rèn)的輸出流是標(biāo)準(zhǔn)輸出,但可以將其重定向到一個(gè)文件,甚至使用 --in-place=.bak
選項(xiàng)重定向到同一個(gè)文件中。
然后再?gòu)南乱粋€(gè)輸入行開始循環(huán)。
sed
命令的語(yǔ)法是:
$ sed --options [optional SCRIPT] [INPUT FILE or STREAM]
找到你要編輯的內(nèi)容
在可視化編輯器中,你通常不需要考慮太多,就能在文本文件中找到你想要修改的內(nèi)容。你的眼睛(或屏幕閱讀器)會(huì)掃描文本,找到你想改變的單詞或你想插入或刪除文本的地方,然后你就可以開始輸入了。而 sed
沒有交互模式,所以你需要告訴它必須滿足什么條件才能運(yùn)行特定的命令。
在這些例子中,假設(shè)一個(gè)名為 example.txt
的文件包含了這樣的文字:
hello
world
This is line three.
Here is the final line.
行號(hào)
指定行號(hào)告訴 sed
只對(duì)文件中的那一行進(jìn)行操作。
例如,下面這條命令選擇文件的第 1 行并打印出來。因?yàn)?nbsp;sed
在處理后的默認(rèn)操作也是打印一行到標(biāo)準(zhǔn)輸出,這樣做的效果就是重復(fù)第一行:
$ sed '1p' example.txt
hello
hello
world
This is line three.
Here is the final line.
你也可以步進(jìn)式指定行號(hào)。例如,1~2
表示每?jī)尚羞x擇一行(“從第一行開始每?jī)尚羞x擇一行”)。指令 1~3
表示從第一行開始,每三行選擇一行:
$ sed '1p' example.txt
hello
hello
world
This is line three.
Here is the final line.
Here is the final line.
行定位
你可以通過使用 $
作為選擇器,只對(duì)文件的最后一行進(jìn)行操作:
$ sed '$p' example.txt
hello
world
This is line three.
Here is the final line.
Here is the final line.
在 GNU sed
中,你可以選擇多行(例如,sed '1,$p'
打印第一行和最后一行)。
反轉(zhuǎn)
任何數(shù)字或位置的選擇,你都可以用感嘆號(hào)(!
)字符反轉(zhuǎn)。下面這將選擇除第一行以外的所有行:
$ sed '1!p' example.txt
hello
world
world
This is line three.
This is line three.
Here is the final line.
Here is the final line.
模式匹配
你可以把模式匹配想象成文字處理器或?yàn)g覽器中的查找操作。你提供一個(gè)詞(一個(gè) 模式),然后選擇了結(jié)果。模式匹配的語(yǔ)法是 /pattern/
:
$ sed '/hello/p' example.txt
hello
hello
world
This is line three.
Here is the final line.
$ sed '/line/p' example.txt
hello
world
This is line three.
This is line three.
Here is the final line.
Here is the final line.
用 Sed 編輯
一旦你找到了你要編輯的內(nèi)容,你就可以執(zhí)行你想要的任何操作。你可以用 sed
中的命令來執(zhí)行編輯。sed
中的命令不是 sed
命令本身。如果這樣說有幫助的話,可以把它們看作是“動(dòng)作”或“動(dòng)詞”或“指令”。
sed
中的命令是單個(gè)字母,例如前面例子中使用的打印命令的 p
。它們一開始可能很難記憶,但和所有事情一樣,你會(huì)隨著練習(xí)而了解它們。
p 代表打印
p
指令打印當(dāng)前模式空間中的任何內(nèi)容。
d 用于刪除
d
指令刪除模式空間:
$ sed '$d' example.txt
hello
world
This is line three.
$ sed '1d' example.txt
world
This is line three.
Here is the final line.
s 用于搜索和替換
s
命令搜索一個(gè)模式并將其替換為其他東西。這可能是 sed
最流行和最隨意的用法,而且它通常是用戶學(xué)習(xí)的第一個(gè)(有時(shí)也是唯一的)sed
命令。幾乎可以肯定它是文本編輯中最有用的命令:
$ sed 's/world/opensource.com/' example.txt
hello
opensource.com
This is line three.
Here is the final line.
在你的替換文本中,也可以使用一些特殊的功能。例如,\L
將替換文本轉(zhuǎn)換為小寫,\l
則只轉(zhuǎn)換下一個(gè)字符。還有其他一些功能,列在 sed
文檔中(你可以用 info sed
命令查看)。
替換子句中的特殊字符 &
指的是匹配到的模式:
$ sed 's/is/\U&/' example.txt
hello
world
ThIS is line three.
Here IS the final line.
你也可以通過特殊的標(biāo)志來影響 s
如何處理它找到的內(nèi)容。g
(應(yīng)該是指 全局)標(biāo)志告訴 s
對(duì)行上找到的所有匹配項(xiàng)進(jìn)行替換,而不僅僅是第一個(gè)匹配項(xiàng):
$ sed 's/is/\U&/g' example.txt
hello
world
ThIS IS line three.
Here IS the final line.
其他重要的標(biāo)志還包括用一個(gè)數(shù)字來表示要影響第幾個(gè)出現(xiàn)的匹配模式:
$ sed 's/is/\U&/2' example.txt
hello
world
This IS line three.
Here is the final line.
w
標(biāo)志,后面跟著一個(gè)文件名,_只有_在有變化的情況下,才會(huì)將匹配的行寫入文件:
$ sed 's/is/\U&/w sed.log' example.txt
hello
world
ThIS is line three.
Here IS the final line.
$ cat sed.log
ThIS is line three.
Here IS the final line.
標(biāo)志可以組合:
$ sed 's/is/\U&/2w sed.log' example.txt
hello
world
This IS line three.
Here is the final line.
$ cat sed.log
This IS line three.
腳本
有很多很棒的網(wǎng)站都有 sed
“單行腳本”,它們給你提供了面向任務(wù)的 sed
命令來解決常見的問題。然而,自己學(xué)習(xí) sed
可以讓你寫出自己的單行腳本,而且這些單行腳本可以根據(jù)你的具體需求來定制。
sed
的腳本可以在終端中寫成一行,也可以保存到文件中,然后用 sed
本身執(zhí)行。我傾向于把小腳本寫成一個(gè)命令,因?yàn)槲野l(fā)現(xiàn)自己在現(xiàn)實(shí)生活中很少重復(fù)使用 sed
命令。當(dāng)我寫一個(gè) sed
腳本時(shí),通常都是針對(duì)一個(gè)文件的。例如,在寫完這篇文章的初稿后,我用 sed
來規(guī)范 “sed” 的大小寫,而這是我可能永遠(yuǎn)也不會(huì)再做的任務(wù)。
你可以向 sed
發(fā)出一系列不同的命令,用分號(hào)(;
)分開。
$ sed '3t ; s/line/\U&/' example.txt
hello
world
This is LINE three.
This is the final line.
帶括號(hào)的范圍改變
你也可以用大括號(hào)({}
)限制哪些結(jié)果受到影響。當(dāng)你將 sed
命令用大括號(hào)括起來時(shí),它們只適用于特定的選擇。例如,“line” 字出現(xiàn)在樣本文本的兩行中。你可以通過聲明所需的匹配條件($
表示最后一行),并將你希望執(zhí)行的 s
命令放在緊隨其后的括號(hào)中,強(qiáng)制 sed
只影響最后一行:
$ sed '$ {s/line/\U&/}' example.txt
hello
world
This is line three.
This is the final LINE.
學(xué)習(xí) Sed
你可以用 sed
做的事情比本文所解釋的多得多。我甚至還沒有涉及到分支(b
)、測(cè)試(t
)、保留空格(H
)和許多其他功能。就像 ed 一樣,sed
可能不是你要用來創(chuàng)建文檔的文本編輯器,甚至不是你需要做的每一個(gè)腳本任務(wù)中使用的文本編輯器,但它是你作為 POSIX 用戶的一個(gè)強(qiáng)大的選擇。學(xué)習(xí) sed
命令的結(jié)構(gòu)以及如何編寫簡(jiǎn)短的腳本可以快速修改大量的文本。閱讀 GNU sed
的info
頁(yè)面,或者 BSD sed
的手冊(cè)頁(yè),看看 sed
能為你做什么。