linux文本處理三劍客之sed

grep擅長查找茵乱,awk擅長分析(select)茂洒,sed擅長批量編輯行

概述

SED的英文全稱是 Stream EDitor,它是一個(gè)簡單而強(qiáng)大的文本解析轉(zhuǎn)換工具瓶竭,在1973-1974年期間由貝爾實(shí)驗(yàn)室的Lee E. McMahon開發(fā)督勺,今天,它已經(jīng)運(yùn)行在所有的主流操作系統(tǒng)上了斤贰。

McMahon創(chuàng)建了一個(gè)通用的行編輯器智哀,最終變成為了SED。SED的很多語法和特性都借鑒了ed編輯器荧恍。設(shè)計(jì)之初瓷叫,它就已經(jīng)支持正則表達(dá)式,SED可以從文件中接受類似于管道的輸入送巡,也可以接受來自標(biāo)準(zhǔn)輸入流的輸入摹菠。

SED由自由軟件基金組織(FSF)開發(fā)和維護(hù)并且隨著GNU/Linux進(jìn)行分發(fā),因此授艰,通常它也稱作 GNU SED辨嗽。對于新手來說,SED的語法看起來可能有些神秘淮腾,但是糟需,一旦掌握了它的語法屉佳,你就可以只用幾行代碼去解決非常復(fù)雜的任務(wù),這就是SED的魅力所在洲押。

SED的典型用途

SED的用途非常廣泛武花,例如:

文本替換

選擇性的輸出文本文件

從文本文件的某處開始編輯

無交互式的對文本文件進(jìn)行編輯等

工作流

在本章中,我們將會探索SED是如何工作的杈帐,要想成為一個(gè)SED專家体箕,你需要知道它的內(nèi)部實(shí)現(xiàn)。SED遵循簡單的工作流:讀取挑童,執(zhí)行和顯示累铅,下圖描述了該工作流:


image.png

image.png
讀取: SED從輸入流(文件站叼,管道或者標(biāo)準(zhǔn)輸入)中讀取一行并且存儲到它叫做 模式空間(pattern buffer) 的內(nèi)部緩沖區(qū)

執(zhí)行: 默認(rèn)情況下娃兽,所有的SED命令都在模式空間中順序的執(zhí)行,除非指定了行的地址尽楔,否則SED命令將會在所有的行上依次執(zhí)行

顯示: 發(fā)送修改后的內(nèi)容到輸出流投储。在發(fā)送數(shù)據(jù)之后,模式空間將會被清空阔馋。

在文件所有的內(nèi)容都被處理完成之前玛荞,上述過程將會重復(fù)執(zhí)行

需要注意的幾點(diǎn)

模式空間 (pattern buffer) 是一塊活躍的緩沖區(qū),在sed編輯器執(zhí)行命令時(shí)它會保存待檢查的文本

默認(rèn)情況下呕寝,所有的SED命令都是在模式空間中執(zhí)行勋眯,因此輸入文件并不會發(fā)生改變

還有另外一個(gè)緩沖區(qū)叫做 保持空間 (hold buffer),在處理模式空間中的某些行時(shí)下梢,可以用保持空間來臨時(shí)保存一些行凡恍。在每一個(gè)循環(huán)結(jié)束的時(shí)候,SED將會移除模式空間中的內(nèi)容怔球,但是該緩沖區(qū)中的內(nèi)容在所有的循環(huán)過程中是持久存儲的。SED命令無法直接在該緩沖區(qū)中執(zhí)行浮还,因此SED允許數(shù)據(jù)在 保持空間 和 模式空間之間切換

初始情況下竟坛,保持空間 和 模式空間 這兩個(gè)緩沖區(qū)都是空的

如果沒有提供輸入文件的話,SED將會從標(biāo)準(zhǔn)輸入接收請求

如果沒有提供地址范圍的話钧舌,默認(rèn)情況下SED將會對所有的行進(jìn)行操作

示例

讓我們創(chuàng)建一個(gè)名為 quote.txt 的文本文件担汤,文件內(nèi)容為著名作家Paulo Coelho的一段名言

$ vi quote.txt 
There is only one thing that makes a dream impossible to achieve: the fear of failure. 
 - Paulo Coelho, The Alchemist

為了理解SED的工作流,我們首先使用SED顯示出quote.txt文件的內(nèi)容洼冻,該示例與cat命令類似

$ sed '' quote.txt
There is only one thing that makes a dream impossible to achieve: the fear of failure.
- Paulo Coelho, The Alchemist

在上面的例子中崭歧,quote.txt是輸入的文件名稱,兩個(gè)單引號是要執(zhí)行的SED命令撞牢。

首先率碾,SED將會讀取quote.txt文件中的一行內(nèi)容存儲到它的模式空間中叔营,然后會在該緩沖區(qū)中執(zhí)行SED命令。在這里所宰,沒有提供SED命令绒尊,因此對該緩沖區(qū)沒有要執(zhí)行的操作,最后它會刪除模式空間中的內(nèi)容并且打印該內(nèi)容到標(biāo)準(zhǔn)輸出仔粥,很簡單的過程婴谱,對吧?

在下面的例子中,SED會從標(biāo)準(zhǔn)輸入流接受輸入

$ sed ''

當(dāng)上述命令被執(zhí)行的時(shí)候躯泰,將會產(chǎn)生下列結(jié)果

There is only one thing that makes a dream impossible to achieve: the fear of failure. 
There is only one thing that makes a dream impossible to achieve: the fear of failure.

在這里谭羔,第一行內(nèi)容是通過鍵盤輸入的內(nèi)容,第二行是SED輸出的內(nèi)容麦向。

從SED會話中退出瘟裸,使用組合鍵ctrl-D (^D)

基礎(chǔ)語法

本章中將會介紹SED中的基本命令和它的命令行使用方法。SED可以用下列兩種方式調(diào)用:

sed [-n] [-e] 'command(s)' files 
sed [-n] -f scriptfile files

第一種方式在命令行中使用單引號指定要執(zhí)行的命令磕蛇,第二種方式則指定了包含SED命令的腳本文件景描。當(dāng)然,這兩種方法也可以同時(shí)使用秀撇,SED提供了很多參數(shù)用于控制這種行為超棺。

讓我們看看如何指定多個(gè)SED命令。SED提供了delete命令用于刪除某些行呵燕,這里讓我們刪除第一行棠绘,第二行和第五行:

首先,使用cat命令顯示文件內(nèi)容

$ cat books.txt 
1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

現(xiàn)在再扭,使用SED移除指定的行氧苍,為了刪除三行,我們使用-e選項(xiàng)指定三個(gè)獨(dú)立的命令

$ sed -e '1d' -e '2d' -e '5d' books.txt
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
6) A Game of Thrones, George R. R. Martin, 864

我們還可以將多個(gè)SED命令寫在一個(gè)文本文件中泛范,然后將該文件作為SED命令的參數(shù)让虐,SED可以對模式空間中的內(nèi)容執(zhí)行文件中的每一個(gè)命令,下面的例子描述了SED的第二種用法

首先罢荡,創(chuàng)建一個(gè)包含SED命令的文本文件赡突,為了便于理解,我們使用與之前相同的SED命令

$ echo -e "1d\n2d\n5d" > commands.txt 
$ cat commands.txt
1d 
2d 
5d

接下來構(gòu)造一個(gè)SED命令去執(zhí)行該操作

$ sed -f commands.txt books.txt
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
6) A Game of Thrones, George R. R. Martin, 864

標(biāo)準(zhǔn)選項(xiàng)

SED支持下列標(biāo)準(zhǔn)選項(xiàng):

-n 默認(rèn)情況下区赵,模式空間中的內(nèi)容在處理完成后將會打印到標(biāo)準(zhǔn)輸出惭缰,該選項(xiàng)用于阻止該行為

    $ sed -n '' quote.txt 

-e 指定要執(zhí)行的命令,使用該參數(shù)笼才,我們可以指定多個(gè)命令漱受,讓我們打印每一行兩次:

    $ sed -e '' -e 'p' quote.txt
    There is only one thing that makes a dream impossible to achieve: the fear of failure.
    There is only one thing that makes a dream impossible to achieve: the fear of failure.

Paulo Coelho, The Alchemist

Paulo Coelho, The Alchemist

-f 指定包含要執(zhí)行的命令的腳本文件

    $ echo "p" > commands
    $
    $ sed -n -f commands quote.txt
    There is only one thing that makes a dream impossible to achieve: the fear of failure.

Paulo Coelho, The Alchemist

GNU選項(xiàng)

這些選項(xiàng)是GNU規(guī)范定義的,可能對于某些版本的SED并不支持骡送。

-n昂羡, --quiet, --slient:與標(biāo)準(zhǔn)的-n選項(xiàng)相同

-e script絮记,--expression=script:與標(biāo)準(zhǔn)的-e選項(xiàng)相同

-f script-file, --file=script-file:與標(biāo)準(zhǔn)的-f選項(xiàng)相同

--follow-symlinks:如果提供該選項(xiàng)的話紧憾,在編輯的文件是符號鏈接時(shí)到千,SED將會跟隨鏈接

-i[SUFFIX],--in-place[=SUFFIX]:該選項(xiàng)用于對當(dāng)前文件進(jìn)行編輯赴穗,如果提供了SUFFIX的話憔四,將會備份原始文件,否則將會覆蓋原始文件

-l N般眉, --line-lenght=N:該選項(xiàng)用于設(shè)置行的長度為N個(gè)字符

--posix:該選項(xiàng)禁用所有的GNU擴(kuò)展

-r了赵,--regexp-extended:該選項(xiàng)將啟用擴(kuò)展的正則表達(dá)式

-u, --unbuffered:指定該選項(xiàng)的時(shí)候甸赃,SED將會從輸入文件中加載最少的數(shù)據(jù)柿汛,并且更加頻繁的刷出到輸出緩沖區(qū)。在編輯tail -f命令的輸出埠对,你不希望等待輸出的時(shí)候該選項(xiàng)是非常有用的络断。

-z,--null-data:默認(rèn)情況下项玛,SED對每一行使用換行符分割貌笨,如果提供了該選項(xiàng)的話,它將使用NULL字符分割行

循環(huán)

與其它編程語言類似襟沮,SED提供了用于控制執(zhí)行流的循環(huán)和分支語句锥惋。

SED中的循環(huán)有點(diǎn)類似于goto語句,SED可以根據(jù)標(biāo)簽(label)跳轉(zhuǎn)到某一行繼續(xù)執(zhí)行开伏,在SED中膀跌,我們可以定義如下的標(biāo)簽:

:label 
:start 
:end 
:up

在上面的示例中,我們創(chuàng)建了四個(gè)標(biāo)簽固灵。

要跳轉(zhuǎn)到指定的標(biāo)簽捅伤,使用 b 命令后面跟著標(biāo)簽名,如果忽略標(biāo)簽名的話巫玻,SED將會跳轉(zhuǎn)到SED文件的結(jié)尾暑认。

b標(biāo)簽用于無條件的跳轉(zhuǎn)到指定的label。

為了更好地理解SED中的循環(huán)和分支大审,讓我們創(chuàng)建一個(gè)名為books2.txt的文本文件,其中包含一些圖書的標(biāo)題和作者信息座哩,下面的示例中會合并圖書的標(biāo)題和作者徒扶,使用逗號分隔。之后搜索所有匹配“Paulo”的行根穷,如果匹配的話就在這一行的開頭添加-姜骡,否則跳轉(zhuǎn)到Print標(biāo)簽导坟,打印出該行內(nèi)容。

$ cat books2.txt
A Storm of Swords
George R. R. Martin
The Two Towers
J. R. R. Tolkien
The Alchemist
Paulo Coelho
The Fellowship of the Ring
J. R. R. Tolkien
The Pilgrimage
Paulo Coelho
A Game of Thrones
George R. R. Martin

$ sed -n '
h;n;H;x
s/\n/, /
/Paulo/!b Print
s/^/- /
:Print
p' books2.txt
A Storm of Swords , George R. R. Martin
The Two Towers , J. R. R. Tolkien
- The Alchemist , Paulo Coelho
The Fellowship of the Ring , J. R. R. Tolkien
- The Pilgrimage , Paulo Coelho
A Game of Thrones , George R. R. Martin

乍看來上述的代碼非常神秘圈澈,讓我們逐步拆解一下

第一行是h;n;H;x這幾個(gè)命令惫周,記得上面我們提到的 保持空間 嗎?第一個(gè)h是指將當(dāng)前模式空間中的內(nèi)容覆蓋到 保持空間中康栈,n用于提前讀取下一行递递,并且覆蓋當(dāng)前模式空間中的這一行,H將當(dāng)前模式空間中的內(nèi)容追加到 保持空間 中啥么,最后的x用于交換模式空間和保持空間中的內(nèi)容登舞。因此這里就是指每次讀取兩行放到模式空間中交給下面的命令進(jìn)行處理

接下來是 s/n/, / 用于將上面的兩行內(nèi)容中的換行符替換為逗號

第三個(gè)命令在不匹配的時(shí)候跳轉(zhuǎn)到Print標(biāo)簽,否則繼續(xù)執(zhí)行第四個(gè)命令

:Print僅僅是一個(gè)標(biāo)簽名悬荣,而p則是print命令

為了提高可讀性菠秒,每一個(gè)命令都占了一行,當(dāng)然氯迂,你也可以把所有命令放在一行

$ sed -n 'h;n;H;x;s/\n/, /;/Paulo/!b Print; s/^/- /; :Print;p' books2.txt

關(guān)于h践叠,Hx命令參考官方手冊 sed, a stream editor 3.6 Less Frequently-Used Commands節(jié)

分支

使用 t 命令創(chuàng)建分支嚼蚀。只有當(dāng)前置條件成功的時(shí)候禁灼,t 命令才會跳轉(zhuǎn)到該標(biāo)簽。

t命令只有在前一個(gè)替換(s)命令執(zhí)行成功的時(shí)候才會執(zhí)行驰坊。

讓我們看一些前面章節(jié)中的例子匾二,與之前不同的是,這次我們將打印四個(gè)連字符"-"拳芙,而之前是一個(gè)察藐。

$ sed -n '
h;n;H;x
s/\n/, /
:Loop
/Paulo/s/^/-/
/----/!t Loop
p' books2.txt
A Storm of Swords , George R. R. Martin
The Two Towers , J. R. R. Tolkien
----The Alchemist , Paulo Coelho
The Fellowship of the Ring , J. R. R. Tolkien
----The Pilgrimage , Paulo Coelho
A Game of Thrones , George R. R. Martin

在上面的例子中,前面兩行與上一節(jié)中講的作用一致舟扎,第三行定義了一個(gè)Loop標(biāo)簽分飞,接下來匹配存在“Paulo”的行,如果存在則在最前面添加一個(gè)-睹限,接下來是我們這里的重點(diǎn):

/----/!t Loop這一行首先檢查上面添加-之后是否滿足四個(gè)-譬猫,如果不滿足則跳轉(zhuǎn)到Loop繼續(xù)執(zhí)行第三行,這樣不停的追加-羡疗,最后如果改行滿足前面有四個(gè)-才繼續(xù)往下執(zhí)行染服。

為了提高可讀性,我們將每一個(gè)SED命令獨(dú)立一行叨恨,我們也可以在同一行中使用:

 sed -n 'h;n;H;x; s/\n/, /; :Loop;/Paulo/s/^/-/; /----/!t Loop; p' books.txt

模式空間和保持空間

模式空間

對任何文件的來說柳刮,最基本的操作就是輸出它的內(nèi)容,為了實(shí)現(xiàn)該目的,在SED中可以使用print命令打印出模式空間中的內(nèi)容秉颗。

首先創(chuàng)建一個(gè)包含行號痢毒,書名,作者和頁碼數(shù)的文件蚕甥,在本文中我們將會使用該文件哪替,你也可以創(chuàng)建任何其它的文件,但是這里我們就創(chuàng)建一個(gè)包含以下內(nèi)容的文件

$ vi books.txt 
1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho,288 
6) A Game of Thrones, George R. R. Martin, 864

執(zhí)行p命令

$ sed 'p' books.txt
1) A Storm of Swords, George R. R. Martin, 1216 
1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864 
6) A Game of Thrones, George R. R. Martin, 864

你可能會疑惑菇怀,為什么每一行被顯示了兩次凭舶?

你還記得SED的工作流嗎?默認(rèn)情況下敏释,SED將會輸出模式空間中的內(nèi)容库快,另外,我們的命令中包含了輸出命令p钥顽,因此每一行被打印兩次义屏。但是不要擔(dān)心梳毙,SED提供了-n參數(shù)用于禁止自動輸出模式空間的每一行的行為

$ sed -n 'p' books.txt 
1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

行尋址

默認(rèn)情況下彭雾,在SED中使用的命令會作用于文本數(shù)據(jù)的所有行靠柑。如果只想將命令作用于特定的行或者某些行禾嫉,則需要使用 行尋址 功能壹置。

在SED中包含兩種形式的行尋址:

以數(shù)字形式表示的行區(qū)間

以文本模式來過濾行

兩種形式都使用相同的語法格式

[address]command

數(shù)字方式的行尋址

在下面的示例中SED只會對第3行進(jìn)行操作

$ sed -n '3p' books.txt 
3) The Alchemist, Paulo Coelho, 197 

當(dāng)然科汗,我們還可以讓SED輸出某些行脐嫂。在SED中使用逗號,分隔輸出行號的范圍晃酒,例如下面的代碼會輸出出2-5行的內(nèi)容

$ sed -n '2,5 p' books.txt 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288

特殊字符 $ 代表了文件的最后一行澳叉,輸出文件的最后一行

$ sed -n '$ p' books.txt 
6) A Game of Thrones, George R. R. Martin, 864 

也可以使用 $ 指定輸出的地址范圍隙咸,下列命令輸出第三行到最后一行

$ sed -n '3,$ p' books.txt
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho,288
6) A Game of Thrones, George R. R. Martin, 864

SED還提供了另外兩種操作符用于指定地址范圍,第一個(gè)是加號(+)操作符成洗,它可以與逗號(,)操作符一起使用五督,例如 M, +n 將會打印出從第M行開始的下n行。下面的示例將會輸出第二行開始的下面四行

$ sed -n '2,+4 p' books.txt 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

我們還可以使用波浪線操作符()指定地址范圍瓶殃,它使用MN的形式充包,它告訴SED應(yīng)該處理M行開始的每N行。例如遥椿,50~5匹配行號50基矮,55,60冠场,65等家浇,讓我們只輸出文件中的奇數(shù)行

$ sed -n '1~2 p' books.txt 
1) A Storm of Swords, George R. R. Martin, 1216 
3) The Alchemist, Paulo Coelho, 197 
5) The Pilgrimage, Paulo Coelho, 288

下面的代碼則是只輸出文件中的偶數(shù)行

$ sed -n '2~2 p' books.txt 
2) The Two Towers, J. R. R. Tolkien, 352 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
6) A Game of Thrones, George R. R. Martin, 864

注意,如果使用的是Mac系統(tǒng)自帶的sed命令碴裙,可能不支持~和+操作符蓝谨」嗑撸可以使用brew install gnu-sed --with-default-names重新安裝GNU-SED。

使用文本模式過濾器

SED編輯器允許指定文本模式來過濾出命令要作用的行譬巫。格式如下:

/pattern/command

必須用正斜線將要指定的pattern封起來。sed編輯器會將該命令作用到包含指定文本模式的行上督笆。

下面的示例中芦昔,將會輸出所有作者為Paulo Coelho的書籍。

$ sed -n '/Paulo/ p' books.txt
3) The Alchemist, Paulo Coelho, 197 
5) The Pilgrimage, Paulo Coelho, 288

模式匹配也可以與數(shù)字形式的尋址同時(shí)使用娃肿,在下面的示例會從第一次匹配到Alchemist開始輸出咕缎,直到第5行為止。

$ sed -n '/Alchemist/, 5 p' books.txt
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288

使用逗號(,)操作符指定匹配多個(gè)匹配的模式料扰。下列的示例將會輸出Two和Pilgrimage之間的所有行

$ sed -n '/Two/, /Pilgrimage/ p' books.txt 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288

在使用文本模式過濾器的時(shí)候凭豪,與數(shù)字方式的行尋址類似,可以使用加號操作符 +晒杈,它會輸出從當(dāng)前匹配位置開始的某幾行嫂伞,下面的示例會從第一次Two出現(xiàn)的位置開始輸出接下來的4行

$ sed -n '/Two/, +4 p' books.txt
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

保持空間

在處理模式空間中的某些行時(shí),可以用保持空間來臨時(shí)保存一些行拯钻。有5條命令可用來操作保持空間

命令

描述

h

將模式空間復(fù)制到保持空間

H

將模式空間附加到保持空間

g

將保持空間復(fù)制到模式空間

G

將保持空間附加到模式空間

x

交換模式空間和保持空間的內(nèi)容

關(guān)于保持空間這里就不在舉例了帖努,前面再循環(huán)部分講解下面這個(gè)命令的時(shí)候我們已經(jīng)對它的使用做了說明。

 $ sed -n 'h;n;H;x;s/\n/, /;/Paulo/!b Print; s/^/- /; :Print;p' books2.txt

基本命令

本章將會講解一些常用的SED命令粪般,主要包括DELETE拼余,WRITE,APPEND亩歹,CHANGE匙监,INSERT,TRANSLATE小作,QUIT亭姥,READ,EXECUTE等命令躲惰。

刪除命令 d

刪除命令格式如下

[address1[,address2]]d 

address1和address2是開始和截止地址致份,它們可以是行號或者字符串匹配模式,這兩種地址都是可選的础拨。

由命令的名稱可以知道氮块,delete 命令是用來執(zhí)行刪除操作的,并且因?yàn)镾ED是基于行的編輯器诡宗,因此我們說該命令是用來刪除行的滔蝉。注意的是,該命令只會移除模式空間中的行塔沃,這樣該行就不會被發(fā)送到輸出流蝠引,但原始內(nèi)容不會改變。

$ sed 'd' books.txt

為什么沒有輸出任何內(nèi)容?默認(rèn)情況下螃概,SED將會對每一行執(zhí)行刪除操作矫夯,這就是該命令為什么沒有在標(biāo)準(zhǔn)輸出中輸出任何內(nèi)容的原因。

下列命令只移除第四行

[jerry]$ sed '4d' books.txt 
1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

SED也接受使用逗號(,)分隔的地址范圍吊洼。我們可以構(gòu)造地址范圍去移除N1到N2行训貌,例如,下列命令將刪除2-4行

$ sed '2, 4 d' books.txt     
1) A Storm of Swords, George R. R. Martin, 1216 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

SED的地址范圍并不僅僅限于數(shù)字冒窍,我們也可以指定模式匹配作為地址递沪,下面的示例會移除所有作者為Paulo Coelho的書籍

$ sed '/Paulo Coelho/d' books.txt 
1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
6) A Game of Thrones, George R. R. Martin, 864

我移除所有以Storm和Fellowship開頭的行

$ sed '/Storm/,/Fellowship/d' books.txt  
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

文件寫入命令 w

SED提供了 write 命令用于將模式空間中的內(nèi)容寫入到文件,與 delete 命令類似综液,下面是 write 命令的語法

[address1[,address2]]w file 

w 指定是寫命令款慨, file 指的是存儲文件內(nèi)容的文件名。使用 file 操作符的時(shí)候要小心谬莹,當(dāng)提供了文件名但是文件不存在的時(shí)候它會自動創(chuàng)建檩奠,如果已經(jīng)存在的話則會覆蓋原文件的內(nèi)容。

下面的SED命令會創(chuàng)建文件books.txt的副本届良,在 w 和 file 之間只能有一個(gè)空格

$ sed -n 'w books.bak' books.txt

上述命令創(chuàng)建了一個(gè)名為 books.bak 的文件笆凌,驗(yàn)證一下兩個(gè)文件的內(nèi)容是否相同

$ diff books.txt books.bak  
$ echo $?

一旦執(zhí)行上述的代碼,你將會得到下列輸出

0

聰明的你可能已經(jīng)想到了士葫,這不就是 cp 命令做的事情嗎乞而!確實(shí)如此,cp 命令也做了同一件事情慢显,但是SED是一個(gè)成熟的工具爪模,使用它你可以只復(fù)制文件中的某些行到新的文件中,如下代碼會存儲文件中的奇數(shù)行到另一個(gè)文件

$ sed -n '2~2 w junk.txt' books.txt  
$ cat junk.txt 
2) The Two Towers, J. R. R. Tolkien, 352 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
6) A Game of Thrones, George R. R. Martin, 864

假設(shè)你希望存儲所有獨(dú)立作者的書到單獨(dú)的文件荚藻。如果人工去做的話屋灌,肯定是非常無聊而且沒有技術(shù)含量的,但是使用SED应狱,你就有了更加聰明的方法去實(shí)現(xiàn)

$ sed -n -e '/Martin/ w Martin.txt' -e '/Paulo/ w Paulo.txt' -e '/Tolkien/ w Tolkien.txt' books.txt    

$ cat Martin.txt
1) A Storm of Swords, George R. R. Martin, 1216 
6) A Game of Thrones, George R. R. Martin, 864

$ cat Paulo.txt
3) The Alchemist, Paulo Coelho, 197 
5) The Pilgrimage, Paulo Coelho, 288

$ cat Tolkien.txt
2) The Two Towers, J. R. R. Tolkien, 352 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432

追加命令 a

文本追加命令語法:

[address]a\ 
Append text 

在第四行之后追加一本新書:

$ sed '4 a 7) Adultry, Paulo Coelho, 234' books.txt 
1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
7) Adultry, Paulo Coelho, 234 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

在命令部分共郭,4指的是行號,a 是append命令疾呻,剩余部分為要追加的文本除嘹。

在文件的結(jié)尾插入一行文本,使用 $ 作為地址

$ sed '$ a 7) Adultry, Paulo Coelho, 234' books.txt
1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864 
7) Adultry, Paulo Coelho, 234

除了行號岸蜗,我們也可以使用文本模式指定地址尉咕,例如,在匹配 The Alchemist 的行之后追加文本

$ sed '/The Alchemist/ a 7) Adultry, Paulo Coelho, 234' books.txt  
1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
7) Adultry, Paulo Coelho, 234 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

行替換命令 c

SED通過 c 提供了 change 和 replace 命令璃岳,該命令幫助我們使用新文本替換已經(jīng)存在的行年缎,當(dāng)提供行的地址范圍時(shí)悔捶,所有的行都被作為一組被替換為單行文本,下面是該命令的語法

[address1[,address2]]c\ 
Replace text

比如单芜,替換文本中的第三行為新的內(nèi)容

$ sed '3 c 3) Adultry, Paulo Coelho, 324' books.txt
1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) Adultry, Paulo Coelho, 324 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

SED也接受模式作為地址

$ sed '/The Alchemist/ c 3) Adultry, Paulo Coelho, 324' books.txt
1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) Adultry, Paulo Coelho, 324 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

多行替換也是支持的蜕该,下面的命令實(shí)現(xiàn)了將第4-6行內(nèi)容替換為單行

$ sed '4, 6 c 4) Adultry, Paulo Coelho, 324' books.txt  
1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
4) Adultry, Paulo Coelho, 324

插入命令 i

插入命令與追加命令類似,唯一的區(qū)別是插入命令是在匹配的位置前插入新的一行洲鸠。

[address]i\ 
Insert text 

下面的命令會在第四行前插入新的一行

$ sed '4 i 7) Adultry, Paulo Coelho, 324' books.txt 
1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
7) Adultry, Paulo Coelho, 324 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

轉(zhuǎn)換命令 y

轉(zhuǎn)換(Translate)命令 y 是唯一可以處理單個(gè)字符的sed編輯器命令蛇损。轉(zhuǎn)換命令格式 如下

[address]y/inchars/outchars/

轉(zhuǎn)換命令會對inchars和outchars值進(jìn)行一對一的映射。inchars中的第一個(gè)字符會被轉(zhuǎn)換為outchars中的第一個(gè)字符坛怪,第二個(gè)字符會被轉(zhuǎn)換成outchars中的第二個(gè)字符。這個(gè)映射過程會一直持續(xù)到處理完指定字符股囊。如果inchars和outchars的長度不同袜匿,則sed編輯器會產(chǎn)生一 條錯誤消息。

$ echo "1 5 15 20" | sed 'y/151520/IVXVXX/'
I V IV XX

輸出隱藏字符命令 l

你能通過直接觀察區(qū)分出單詞是通過空格還是tab進(jìn)行分隔的嗎稚疹?顯然是不能的居灯,但是SED可以為你做到這點(diǎn)。使用l命令(英文字母L的小寫)可以顯示文本中的隱藏字符(例如t或者$字符)内狗。

[address1[,address2]]l 
[address1[,address2]]l [len]

為了測試該命令怪嫌,我們首先將books.txt中的空格替換為tab。

$ sed 's/ /\t/g' books.txt > junk.txt 

接下來執(zhí)行l(wèi)命令

$ sed -n 'l' junk.txt
1)\tStorm\tof\tSwords,\tGeorge\tR.\tR.\tMartin,\t1216\t$
2)\tThe\tTwo\tTowers,\tJ.\tR.\tR.\tTolkien,\t352\t$
3)\tThe\tAlchemist,\tPaulo\tCoelho,\t197\t$
4)\tThe\tFellowship\tof\tthe\tRing,\tJ.\tR.\tR.\tTolkien,\t432\t$
5)\tThe\tPilgrimage,\tPaulo\tCoelho,\t288\t$
6)\tA\tGame\tof\tThrones,\tGeorge\tR.\tR.\tMartin,\t864$

使用l命令的時(shí)候柳沙,一個(gè)很有趣的特性是我們可以使用它來實(shí)現(xiàn)文本按照指定的寬度換行岩灭。

$ sed -n 'l 25' books.txt
1) Storm of Swords, Geor\
ge R. R. Martin, 1216 $
2) The Two Towers, J. R.\
 R. Tolkien, 352 $
3) The Alchemist, Paulo \
Coelho, 197 $
4) The Fellowship of the\
 Ring, J. R. R. Tolkien,\
 432 $
5) The Pilgrimage, Paulo\
 Coelho, 288 $
6) A Game of Thrones, Ge\
orge R. R. Martin, 864$

上面的示例中在l命令后跟了一個(gè)數(shù)字25,它告訴SED按照每行25個(gè)字符進(jìn)行換行赂鲤,如果指定這個(gè)數(shù)字為0的話噪径,則只有在存在換行符的情況下才進(jìn)行換行。

l命令是GNU-SED的一部分数初,其它的一些變體中可能無法使用該命令找爱。

退出命令 q

在SED中,可以使用Quit命令退出當(dāng)前的執(zhí)行流

[address]q 
[address]q [value]

需要注意的是泡孩,q命令不支持地址范圍车摄,只支持單個(gè)地址匹配。默認(rèn)情況下SED會按照讀取仑鸥、執(zhí)行吮播、重復(fù)的工作流執(zhí)行,但當(dāng)它遇到q命令的時(shí)候锈候,它會退出當(dāng)前的執(zhí)行流薄料。

$ sed '3 q' books.txt
1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197

$ sed '/The Alchemist/ q' books.txt 
1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197

q命令也支持提供一個(gè)value,這個(gè)value將作為程序的返回代碼返回

$ sed '/The Alchemist/ q 100' books.txt
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197

$ echo $? 
100

文件讀取命令 r

在SED中泵琳,我們可以讓SED使用Read命令從外部文件中讀取內(nèi)容并且在滿足條件的時(shí)候顯示出來摄职。

[address]r file

需要注意的是誊役,r命令和文件名之間必須只有一個(gè)空格。

下面的示例會打開junk.txt文件谷市,將其內(nèi)容插入到books.txt文件的第三行之后

$ echo "This is junk text." > junk.txt 
$ sed '3 r junk.txt' books.txt 
1) A Storm of Swords, George R. R. Martin, 1216 
2) The Two Towers, J. R. R. Tolkien, 352 
3) The Alchemist, Paulo Coelho, 197 
This is junk text. 
4) The Fellowship of the Ring, J. R. R. Tolkien, 432 
5) The Pilgrimage, Paulo Coelho, 288 
6) A Game of Thrones, George R. R. Martin, 864

r命令也支持地址范圍蛔垢,例如3, 5 r junk.txt會在第三行,第四行迫悠,第五行后面分別插入junk.txt的內(nèi)容

執(zhí)行外部命令 e

如果你看過三十分鐘學(xué)會AWK一文鹏漆,你可能已經(jīng)知道了在AWK中可以執(zhí)行外部的命令,那么在SED中我們是否也可以這樣做创泄?

答案是肯定的艺玲,在SED中,我們可以使用e命令執(zhí)行外部命令

[address1[,address2]]e [command]

下面的命令會在第三行之前執(zhí)行date命令

$ sed '3 e date' books.txt
1) Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
2016年11月29日 星期二 22時(shí)46分14秒 CST
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864

另一個(gè)示例

$ sed '3,5 e who' books.txt
1) Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
mylxsw   console  Nov 29 19:30
mylxsw   ttys000  Nov 29 22:45
3) The Alchemist, Paulo Coelho, 197
mylxsw   console  Nov 29 19:30
mylxsw   ttys000  Nov 29 22:45
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
mylxsw   console  Nov 29 19:30
mylxsw   ttys000  Nov 29 22:45
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864

如果你仔細(xì)觀察e命令的語法鞠抑,你會發(fā)現(xiàn)其實(shí)它的command參數(shù)是可選的饭聚。在沒有提供外部命令的時(shí)候,SED會將模式空間中的內(nèi)容作為要執(zhí)行的命令搁拙。

$ echo -e "date\ncal\nuname" > commands.txt
$ cat commands.txt
date
cal
uname
$ sed 'e' commands.txt
2016年11月29日 星期二 22時(shí)50分30秒 CST
    十一月 2016
日 一 二 三 四 五 六
       1  2  3  4  5
 6  7  8  9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30

Darwin

排除命令 !

感嘆號命令(!)用來排除命令秒梳,也就是讓原本會起作用的命令不起作用。

$ sed -n '/Paulo/p' books.txt
3) The Alchemist, Paulo Coelho, 197
5) The Pilgrimage, Paulo Coelho, 288
$ sed -n '/Paulo/!p' books.txt
1) Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
6) A Game of Thrones, George R. R. Martin, 864

如上例所示箕速,p命令原先是只輸出匹配Paulo的行酪碘,添加!之后,變成了只輸出不匹配Paulo的行盐茎。

$ sed -n '1!G; h; $p' books.txt
6) A Game of Thrones, George R. R. Martin, 864
5) The Pilgrimage, Paulo Coelho, 288
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
3) The Alchemist, Paulo Coelho, 197
2) The Two Towers, J. R. R. Tolkien, 352
1) Storm of Swords, George R. R. Martin, 1216

上面的命令實(shí)現(xiàn)了類似tac命令類似的輸出兴垦,將文本內(nèi)容倒序輸出⊥ノ兀看起來有些晦澀難懂滑进,分解一下卻十分簡單:

  1. 1!G 這句的意思是出了第一行之外,處理每一行的時(shí)候都將保持空間中的內(nèi)容追加到模式空間(正序->倒序)

  2. h 將模式空間中的內(nèi)容復(fù)制到保持空間以備下一行匹配的時(shí)候追加到下一行的后面

  3. $p 如果匹配到最后一行的話則輸出模式空間中的內(nèi)容

  4. 上述步驟不斷重復(fù)直到文本結(jié)束剛好將文件內(nèi)容翻轉(zhuǎn)了一次

多行命令

在使用sed編輯器的基礎(chǔ)命令時(shí)募谎,你可能注意到了一個(gè)局限扶关。所有的sed編輯器命令都是針對單行數(shù)據(jù)執(zhí)行操作的。在sed編輯器讀取數(shù)據(jù)流時(shí)数冬,它會基于換行符的位置將數(shù)據(jù)分成行节槐。sed編輯器根據(jù)定義好的腳本命令一次處理一行數(shù)據(jù),然后移到下一行重復(fù)這個(gè)過程拐纱。

幸運(yùn)的是铜异,sed編輯器的設(shè)計(jì)人員已經(jīng)考慮到了這種情況,并設(shè)計(jì)了對應(yīng)的解決方案秸架。sed編輯器包含了三個(gè)可用來處理多行文本的特殊命令揍庄。

N:將數(shù)據(jù)流中的下一行加進(jìn)來創(chuàng)建一個(gè)多行組來處理

D:刪除多行組中的一行

P:打印多行組中的一行

N - 加載下一行

默認(rèn)情況下,SED是基于單行進(jìn)行操作的东抹,有些情況下我們可能需要使用多行進(jìn)行編輯蚂子,啟用多行編輯使用N命令沃测,與n不同的是,N并不會清除食茎、輸出模式空間的內(nèi)容蒂破,而是采用了追加模式。

[address1[,address2]]N

下面的示例將會把books2.txt中的標(biāo)題和作者放到同一行展示别渔,并且使用逗號進(jìn)行分隔

$ sed 'N; s/\n/,/g' books2.txt
A Storm of Swords ,George R. R. Martin
The Two Towers ,J. R. R. Tolkien
The Alchemist ,Paulo Coelho
The Fellowship of the Ring ,J. R. R. Tolkien
The Pilgrimage ,Paulo Coelho
A Game of Thrones ,George R. R. Martin

D - 刪除多行中的一行

sed編輯器提供了多行刪除命令D附迷,它只刪除模式空間中的第一行。該命令會刪除到換行符(含 換行符)為止的所有字符哎媚。

$ echo '\nThis is the header line.\nThis is a data line.\n\nThis is the last line.' | sed '/^$/{N; /header/D}'
This is the header line.
This is a data line.

This is the last line.

P - 輸出多行中的一行

P命令用于輸出N命令創(chuàng)建的多行文本的模式空間中的第一行喇伯。

[address1[,address2]]P 

例如下面的命令只輸出了圖書的標(biāo)題

$ sed -n 'N;P' books2.txt
A Storm of Swords
The Two Towers
The Alchemist
The Fellowship of the Ring
The Pilgrimage
A Game of Thrones

其它命令

n - 單行next

小寫的n命令會告訴sed編輯器移動到數(shù)據(jù)流中的下一文本行,并且覆蓋當(dāng)前模式空間中的行拨与。

$ cat data1.txt 
This is the header line.

This is a data line.

This is the last line.
$ sed '/header/{n ; d}' data1.txt 
This is the header line.
This is a data line.

This is the last line.

上面的命令中艘刚,首先會匹配包含header的行,之后將移動到數(shù)據(jù)流的下一行截珍,這里是一個(gè)空行,然后執(zhí)行d命令對改行進(jìn)行刪除箩朴,所有就看到了這樣的結(jié)果:第一個(gè)空行被刪除掉了岗喉。

v - SED版本檢查

v命令用于檢查SED的版本,如果版本大于參數(shù)中的版本則正常執(zhí)行炸庞,否則失敗

[address1[,address2]]v [version]

例如

$ sed --version
sed (GNU sed) 4.2.2

$ sed 'v 4.2.3' books.txt
sed: -e expression #1, char 7: expected newer version of sed

$ sed 'v 4.2.2' books.txt
1) Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864

特殊字符

在SED中提供了兩個(gè)可以用作命令的特殊字符:= 和 & 钱床。

=命令

=命令用于輸出行號,語法格式為

[/pattern/]= 
[address1[,address2]]=

例如為每一行輸出行號

$ sed '=' books2.txt
1
A Storm of Swords
2
George R. R. Martin
...

只為1-4行輸出行號

$ sed '1, 4=' books2.txt
1
A Storm of Swords
2
George R. R. Martin
3
The Two Towers
4
J. R. R. Tolkien
The Alchemist
Paulo Coelho
The Fellowship of the Ring
J. R. R. Tolkien
The Pilgrimage
Paulo Coelho
A Game of Thrones
George R. R. Martin

匹配Paulo的行輸出行號

$ sed '/Paulo/ =' books2.txt
A Storm of Swords
George R. R. Martin
The Two Towers
J. R. R. Tolkien
The Alchemist
6
Paulo Coelho
The Fellowship of the Ring
J. R. R. Tolkien
The Pilgrimage
10
Paulo Coelho
A Game of Thrones
George R. R. Martin

最后一行輸出行號埠居,這個(gè)命令比較有意思了查牌,可以用于輸出文件總共有多少行

$ sed -n '$ =' books2.txt
12

&命令

特殊字符&用于存儲匹配模式的內(nèi)容,通常與替換命令s一起使用滥壕。

$ sed 's/[[:digit:]]/Book number &/' books.txt
Book number 1) Storm of Swords, George R. R. Martin, 1216
Book number 2) The Two Towers, J. R. R. Tolkien, 352
Book number 3) The Alchemist, Paulo Coelho, 197
Book number 4) The Fellowship of the Ring, J. R. R. Tolkien, 432
Book number 5) The Pilgrimage, Paulo Coelho, 288
Book number 6) A Game of Thrones, George R. R. Martin, 864

上述命令用于匹配每一行第一個(gè)數(shù)字纸颜,在其前面添加 Book number 。而下面這個(gè)命令則匹配最后一個(gè)數(shù)字绎橘,并修改為Pages =胁孙。其中[[:digit:]]* *$可能比較費(fèi)解,這一部分其實(shí)是:匹配0個(gè)或多個(gè)數(shù)字+0個(gè)或多個(gè)空格+行尾称鳞。

sed 's/[[:digit:]]* *$/Pages = &/' books.txt
1) Storm of Swords, George R. R. Martin, Pages = 1216
2) The Two Towers, J. R. R. Tolkien, Pages = 352
3) The Alchemist, Paulo Coelho, Pages = 197
4) The Fellowship of the Ring, J. R. R. Tolkien, Pages = 432
5) The Pilgrimage, Paulo Coelho, Pages = 288
6) A Game of Thrones, George R. R. Martin, Pages = 864

字符串

替換命令 s

文本替換命令非常常見涮较,其格式如下

[address1[,address2]]s/pattern/replacement/[flags]

在前面我們使用的books.txt文件中,我們使用逗號“,”分隔每一列冈止,下面的示例中狂票,我們會使用替換命令將其替換為管道符“|”:

$ sed 's/,/ |/' books.txt
1) Storm of Swords | George R. R. Martin, 1216
2) The Two Towers | J. R. R. Tolkien, 352
3) The Alchemist | Paulo Coelho, 197
4) The Fellowship of the Ring | J. R. R. Tolkien, 432
5) The Pilgrimage | Paulo Coelho, 288
6) A Game of Thrones | George R. R. Martin, 864

是不是覺得哪里不對?相信你已經(jīng)發(fā)現(xiàn)熙暴,每一行的第二個(gè)逗號都沒有被替換闺属,只有第一個(gè)被替換了慌盯,確實(shí)如此,在SED中屋剑,使用替換命令的時(shí)候默認(rèn)只會對第一個(gè)匹配的位置進(jìn)行替換润匙。使用g選項(xiàng)告訴SED對所有內(nèi)容進(jìn)行替換:

$ sed 's/,/ | /g' books.txt
1) Storm of Swords |  George R. R. Martin |  1216
2) The Two Towers |  J. R. R. Tolkien |  352
3) The Alchemist |  Paulo Coelho |  197
4) The Fellowship of the Ring |  J. R. R. Tolkien |  432
5) The Pilgrimage |  Paulo Coelho |  288
6) A Game of Thrones |  George R. R. Martin |  864

如果對匹配模式(或地址范圍)的行進(jìn)行替換,則只需要在s命令前添加地址即可唉匾。比如只替換匹配The Pilgrimage的行: sed '/The Pilgrimage/ s/,/ | /g' books.txt

還有一些其它的選項(xiàng)孕讳,這里就簡單的描述一下,不在展開講解

數(shù)字n: 只替換第n次匹配巍膘,比如sed 's/,/ | /2' books.txt厂财,只替換每行中第二個(gè)逗號

p:只輸出改變的行,比如sed -n 's/Paulo Coelho/PAULO COELHO/p' books.txt

w:存儲改變的行到文件峡懈,比如sed -n 's/Paulo Coelho/PAULO COELHO/w junk.txt' books.txt

i:匹配時(shí)忽略大小寫璃饱,比如sed -n 's/pAuLo CoElHo/PAULO COELHO/pi' books.txt

在執(zhí)行替換操作的時(shí)候,如果要替換的內(nèi)容中包含/肪康,這個(gè)時(shí)候怎么辦荚恶?很簡單,添加轉(zhuǎn)義操作符磷支。

$ echo "/bin/sed" | sed 's/\/bin\/sed/\/home\/mylxsw\/src\/sed\/sed-4.2.2\/sed/'
/home/mylxsw/src/sed/sed-4.2.2/sed

上面的命令中谒撼,我們使用對/進(jìn)行了轉(zhuǎn)義,不過表達(dá)式已經(jīng)看起來非常難看了雾狈,在SED中還可以使用|廓潜,@,^善榛,!作為命令的分隔符辩蛋,所以,下面的幾個(gè)命令和上面的是等價(jià)的

echo "/bin/sed" | sed 's|/bin/sed|/mylxsw/mylxsw/src/sed/sed-4.2.2/sed|'
echo "/bin/sed" | sed 's@/bin/sed@/home/mylxsw/src/sed/sed-4.2.2/sed@'
echo "/bin/sed" | sed 's^/bin/sed^/home/mylxsw/src/sed/sed-4.2.2/sed^'
echo "/bin/sed" | sed 's!/bin/sed!/home/mylxsw/src/sed/sed-4.2.2/sed!'

匹配子字符串

前面我們學(xué)習(xí)了替換命令的用法移盆,現(xiàn)在讓我們看看如何獲取匹配文本中的某個(gè)子串悼院。

在SED中,使用(和)對匹配的內(nèi)容進(jìn)行分組咒循,使用N的方式進(jìn)行引用樱蛤。請看下面示例

$ echo "Three One Two" | sed 's|\(\w\+\) \(\w\+\) \(\w\+\)|\2 \3 \1|'
One Two Three

我們輸出了Three,One剑鞍,Two三個(gè)單詞,在SED的替換規(guī)則中蚁署,使用空格分隔了三小段正則表達(dá)式(w+)來匹配每一個(gè)單詞,后面使用1哪痰,遂赠,2跷睦,3分別引用它們的值肋演。

管理模式

前面已經(jīng)講解過模式空間和保持空間的用法,在本節(jié)中我們將會繼續(xù)探索它們的用法蜕乡。

本部分內(nèi)容暫未更新梗夸,請關(guān)注程序猿成長計(jì)劃 項(xiàng)目,我將最先在Github的這個(gè)倉庫中更新最新內(nèi)容反症。

正則表達(dá)式

這一部分就是標(biāo)準(zhǔn)正則表達(dá)式的一些特殊字符以元字符,比較熟悉的請略過憨降。

標(biāo)準(zhǔn)正則表達(dá)式

^
匹配行的開始该酗。

$ sed -n '/^The/ p' books2.txt
The Two Towers, J. R. R. Tolkien 
The Alchemist, Paulo Coelho 
The Fellowship of the Ring, J. R. R. Tolkien 
The Pilgrimage, Paulo Coelho

$
匹配行的結(jié)尾

$ sed -n '/Coelho$/ p' books2.txt 
The Alchemist, Paulo Coelho 
The Pilgrimage, Paulo Coelho

.
匹配單個(gè)字符(除行尾)

$ echo -e "cat\nbat\nrat\nmat\nbatting\nrats\nmats" | sed -n '/^..t$/p'
cat
bat
rat
mat

[]
匹配字符集

$ echo -e "Call\nTall\nBall" | sed -n '/[CT]all/ p'
Call
Tall

[^]
排除字符集

$ echo -e "Call\nTall\nBall" | sed -n '/[^CT]all/ p'
Ball

[-]
字符范圍呜魄。

$ echo -e "Call\nTall\nBall" | sed -n '/[C-Z]all/ p' 
Call 
Tall

? 莱衩,+ ,*
分別對應(yīng)0次到1次睹晒,一次到多次括细,0次到多次匹配。

{n} 锉试,{n,} ,{m, n}
精確匹配N次呆盖,至少匹配N次,匹配M-N次
|
或操作应又。

$ echo -e "str1\nstr2\nstr3\nstr4" | sed -n '/str\(1\|3\)/ p' 
str1
str3

POSIX兼容的正則

主要包含[:alnum:],[:alpha:]尤筐,[:blank:]席里,[:digit:],[:lower:]改基,[:upper:]咖为,[:punct:],[:space:]鸣哀,這些基本都見名之意,不在贅述我衬。

元字符

s
匹配單個(gè)空白內(nèi)容

$ echo -e "Line\t1\nLine2" | sed -n '/Line\s/ p'
Line 1 

S
匹配單個(gè)非空白內(nèi)容饰恕。

w , W
單個(gè)單詞破加、非單詞雹嗦。

常用代碼段

Cat命令

模擬cat命令比較簡單,有下面兩種方式

$ sed '' books.txt
1) Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864

$ sed -n 'p' books.txt
1) Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage, Paulo Coelho, 288
6) A Game of Thrones, George R. R. Martin, 864

移除空行

$ echo -e "Line #1\n\n\nLine #2" | sed '/^$/d'
Line #1
Line #2

刪除連續(xù)空行

$ echo -e "Line #1\n\n\nLine #2" | sed '/./,/^$/!d'
Line #1

Line #2

刪除開頭的空行

$ echo -e "\nLine #1\n\nLine #2" | sed '/./,$!d'
Line #1

Line #2

刪除結(jié)尾的空行

$ echo -e "\nLine #1\nLine #2\n\n" | sed ':start /^\n*$/{$d; N; b start }'

Line #1

Line #2

過濾所有的html標(biāo)簽

$ cat html.txt
<html>
<head>
    <title>This is the page title</title>
</head>
<body>
    <p> This is the <b>first</b> line in the Web page.
    This should provide some <i>useful</i> information to use in our sed script.
</body>
</html>                                                                                  
$ sed 's/<[^>]*>//g ; /^$/d' html.txt
    This is the page title
     This is the first line in the Web page.
    This should provide some useful information to use in our sed script.

從C++程序中移除注釋

有下面這樣一個(gè)cpp文件

$ cat hello.cpp
#include <iostream> 
using namespace std; 
int main(void) 
{ 
   // Displays message on stdout. 
   cout >> "Hello, World !!!" >> endl;  
   return 0; // Return success. 
}

執(zhí)行下面的命令可以移除注釋

$ sed 's|//.*||g' hello.cpp
#include <iostream>
using namespace std;
int main(void)
{

   cout >> "Hello, World !!!" >> endl;
   return 0;
 }

為某些行添加注釋

$ sed '3,5 s/^/#/' hello.sh 
#!/bin/bash 
#pwd 
#hostname 
#uname -a 
who 
who -r 
lsb_release -a

實(shí)現(xiàn)Wc -l命令

wc -l命令用于統(tǒng)計(jì)文件中的行數(shù)锭环,使用SED也可以模擬該命令

$ wc -l hello.cpp
       9 hello.cpp
$ sed -n '$ =' hello.cpp
9

模擬實(shí)現(xiàn)head命令

head命令用于輸出文件中的前10行內(nèi)容田藐。

$ head books2.txt
A Storm of Swords
George R. R. Martin
The Two Towers
J. R. R. Tolkien
The Alchemist
Paulo Coelho
The Fellowship of the Ring
J. R. R. Tolkien
The Pilgrimage
Paulo Coelho

使用SED中的sed '10 q'可以模擬它的實(shí)現(xiàn)

$ sed '10 q' books.txt 
A Storm of Swords 
George R. R. Martin 
The Two Towers 
J. R. R. Tolkien 
The Alchemist 
Paulo Coelho 
The Fellowship of the Ring 
J. R. R. Tolkien 
The Pilgrimage
Paulo Coelho

模擬tail -1命令

tail -1輸出文件的最后一行。

$ cat test.txt
Line #1 
Line #2 

$ tail -1 test.txt
Line #2
$ sed $ sed -n '$p' test.txt
Line #2

模擬Dos2unix命令

在DOS環(huán)境中鹤竭,換行符是使用CR/LF兩個(gè)字符一起表示的景醇,下面命令模擬了dos2unix命令轉(zhuǎn)換這些換行符為UNIX換行符。

在GNU/Linux環(huán)境中吧寺,CR/LF通常使用"^M"(不是簡單的兩個(gè)符號組合散劫,請使用快捷鍵Ctrl+v,Ctrl+m輸入)進(jìn)行表示。

$ echo -e "Line #1\r\nLine #2\r" > test.txt
$ file test.txt
test.txt: ASCII text, with CRLF line terminators
$ sed 's/^M$//' test.txt > new.txt
$ file new.txt
new.txt: ASCII text
$ cat -vte new.txt
Line #1$
Line #2$

模擬Unix2dos命令

$ file new.txt
new.txt: ASCII text
$ sed 's/$/\r/' new.txt > new2.txt
$ file new2.txt
new2.txt: ASCII text, with CRLF line terminators

$ cat -vte new2.txt
Line #1^M$
Line #2^M$

模擬cat -E命令

cat -E命令會在每一行的行尾輸出一個(gè)$符號赖条。

$ echo -e "Line #1\nLine #2" | cat -E
Line #1$
Line #2$
$ echo -e "Line #1\nLine #2" | sed 's|$|&$|'
Line #1$
Line #2$

注意常熙,在Mac下不支持cat -E,可以直接使用sed代替

模擬cat -ET命令

cat -ET命令不僅對每一行的行尾添加$裸卫,還會將每一行中的TAB顯示為^I。

$ echo -e "Line #1\tLine #2" | cat -ET
Line #1^ILine #2$
$ echo -e "Line #1\tLine #2" | sed -n 'l' | sed 'y/\\t/^I/'
Line #1^ILine #2$

模擬nl命令

命令nl可以為輸入內(nèi)容的每一行添加行號茧泪,記得之前介紹的=操作符吧聋袋,在SED中我們可以用它來實(shí)現(xiàn)與nl命令類似的功能。

$ echo -e "Line #1\nLine #2" |nl
     1    Line #1
     2    Line #2
$ echo -e "Line #1\nLine #2" | sed = |  sed 'N;s/\n/\t/'
1    Line #1
2    Line #2

上面的SED命令使用了兩次,第一次使用=操作符為每一行輸出行號刀荒,注意這個(gè)行號是獨(dú)占一行的,因此使用管道符連接了第二個(gè)SED命令干毅,每次讀取兩行泼返,將換行符替換為Tab,這樣就模擬出了nl命令的效果。

模擬cp命令

$ sed -n 'w dup.txt' data.txt
$ diff data.txt dup.txt
$ echo $?
0

模擬expand命令

expand命令會轉(zhuǎn)換輸入中的TAB為空格叫乌,在SED中也可以模擬它

$ echo -e "One\tTwo\tThree" > test.txt
$ expand test.txt > expand.txt
$ sed 's/\t/     /g' test.txt > new.txt
$ diff new.txt expand.txt
$ echo $?
0

模擬tee命令

tee命令會將數(shù)據(jù)輸出到標(biāo)準(zhǔn)輸出的同時(shí)寫入文件徽缚。

$ echo -e "Line #1\nLine #2" | tee test.txt  
Line #1 
Line #2 

在SED中,實(shí)現(xiàn)該命令非常簡單

$ sed -n 'p; w new.txt' test.txt
One Two Three

模擬cat -s命令

cat -s命令會將輸入文件中的多行空格合并為一行排宰。

$ echo -e "Line #1\n\n\n\nLine #2\n\n\nLine #3" | cat -s
Line #1

Line #2

Line #3

在SED中實(shí)現(xiàn)

$ echo -e "Line #1\n\n\n\nLine #2\n\n\nLine #3" | sed '/./,/^$/!d'
Line #1

Line #2

Line #3

這里需要注意的是/./,/^/!d這個(gè)命令板甘,它的意思是匹配區(qū)間/./到/^,區(qū)間的開始會匹配至少包含一個(gè)字符的行盐类,結(jié)束會匹配一個(gè)空行痕寓,在這個(gè)區(qū)間中的行不會被刪除。

模擬grep命令

$ echo -e "Line #1\nLine #2\nLine #3" | grep 'Line #1'
Line #1
$ echo -e "Line #1\nLine #2\nLine #3" | sed -n '/Line #1/p'
Line #1

模擬grep -v命令

$ echo -e "Line #1\nLine #2\nLine #3" | grep -v 'Line #1'
Line #2
Line #3
$ echo -e "Line #1\nLine #2\nLine #3" | sed -n '/Line #1/!p'
Line #2
Line #3

模擬tr命令

tr命令用于字符轉(zhuǎn)換

$ echo "ABC" | tr "ABC" "abc"
abc
$ echo "ABC" | sed 'y/ABC/abc/'
abc
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末硬毕,一起剝皮案震驚了整個(gè)濱河市礼仗,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌韭脊,老刑警劉巖单旁,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蔫饰,居然都是意外死亡愉豺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門杖剪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人盛嘿,你說我怎么就攤上這事『⒗蓿” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵狈邑,是天一觀的道長蚤认。 經(jīng)常有香客問我,道長蘸嘶,這世上最難降的妖魔是什么陪汽? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮况增,結(jié)果婚禮上训挡,老公的妹妹穿的比我還像新娘。我一直安慰自己澜薄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布颊艳。 她就那樣靜靜地躺著忘分,像睡著了一般。 火紅的嫁衣襯著肌膚如雪戒悠。 梳的紋絲不亂的頭發(fā)上舟山,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天,我揣著相機(jī)與錄音寒矿,去河邊找鬼。 笑死符相,一個(gè)胖子當(dāng)著我的面吹牛蠢琳,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蓝牲,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼泰讽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了佛玄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤梦抢,失蹤者是張志新(化名)和其女友劉穎惑申,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體圈驼,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡望几,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了靴迫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片楼誓。...
    茶點(diǎn)故事閱讀 40,137評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖主守,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情参淫,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布鞋既,位于F島的核電站,受9級特大地震影響邑闺,放射性物質(zhì)發(fā)生泄漏棕兼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一蹭沛、第九天 我趴在偏房一處隱蔽的房頂上張望章鲤。 院中可真熱鬧,春花似錦败徊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至辜妓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間酪夷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工晚岭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留勋功,地道東北人辅甥。 一個(gè)月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像要销,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子疏咐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 本文承接之前寫的三十分鐘學(xué)會AWK一文浑塞,在學(xué)習(xí)完AWK之后,趁熱打鐵又學(xué)習(xí)了一下SED掏愁,不得不說這兩個(gè)工具真的堪稱...
    mylxsw閱讀 4,401評論 3 74
  • 一卵牍、前言 我們都知道,在Linux中一切皆文件糊昙,比如配置文件,日志文件萝衩,啟動文件等等。如果我們相對這些文件進(jìn)行一些...
    以七v為書閱讀 1,518評論 0 5
  • “文本三劍客”中猩谊,grep是文本過濾器祭刚,而sed是基于行的文本流編輯器。sed是將文件中的文本逐行讀取到內(nèi)存中進(jìn)行...
    學(xué)渣角鹿白閱讀 591評論 0 3
  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經(jīng)改了很多 但是錯誤還是無法避免 以后資料會慢慢更新 大...
    數(shù)據(jù)革命閱讀 12,168評論 2 33
  • +(NSString *)PostImagesToServer:(NSString *) strUrl dicPo...
    Daimer閱讀 500評論 0 2