Sed and awk 筆記之 sed 篇:高級(jí)命令(二)

sed篇總共分成6章:(簡(jiǎn)書(shū)版)

Sed&awk筆記之sed篇:簡(jiǎn)單介紹

Sed&awk筆記之sed篇:模式空間與地址匹配

Sed&awk筆記之sed篇:sed基礎(chǔ)命令

Sed&awk筆記之sed篇:高級(jí)命令(一)

Sed&awk筆記之sed篇:高級(jí)命令(二)

Sed&awk筆記之sed篇:實(shí)戰(zhàn)

上一篇中介紹了N/D/P三個(gè)命令燕侠,它們可以形成多行的模式空間穗慕,在一點(diǎn)程度上彌補(bǔ)了單行模式空間的不足俺榆,我們用sed編輯文本的能力又進(jìn)了一步。模式空間是sed內(nèi)部維護(hù)的一個(gè)緩存空間蝠猬,它存放著讀入的一行或者多行內(nèi)容。但是模式空間的一個(gè)限制是無(wú)法保存模式空間中被處理的行,因此sed又引入了另外一個(gè)緩存空間——模式空間(Hold Space)辆雾。

保持空間

保持空間用于保存模式空間的內(nèi)容万伤,模式空間的內(nèi)容可以復(fù)制到保持空間窒悔,同樣地保持空間的內(nèi)容可以復(fù)制回模式空間。sed提供了幾組命令用來(lái)完成復(fù)制的工作敌买,其它命令無(wú)法匹配也不能修改模式空間的內(nèi)容简珠。

操作保持空間的命令如下所示:

名稱命令說(shuō)明

保存(Hold)h/H將模式空間的內(nèi)容復(fù)制或者追加到保持空間

取回(Get)g/G將保持空間的內(nèi)容復(fù)制或者追加到模式空間

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

這幾組命令提供了保存、取回以及交換三個(gè)動(dòng)作,交換命令比較容易理解聋庵,保存命令和取回命令都有大寫(xiě)和小寫(xiě)兩種形式膘融,這兩種形式的區(qū)別是小寫(xiě)的是將會(huì)覆蓋目的空間的內(nèi)容,而大寫(xiě)的是將內(nèi)容追加到目的空間祭玉,追加的內(nèi)容和原有的內(nèi)容是以\n分隔氧映。

基本使用

我們隨便試試這幾個(gè)命令,假設(shè)有如下測(cè)試文本:

$ cat text121122111222

1. 首先脱货,僅使用h/H或者g/G命令:

使用h命令:

$ sed'h'text121122111222

使用G命令:

$ sed'G'text121122111222

前者返回的結(jié)果正常岛都,因?yàn)閺?fù)制到保持空間的內(nèi)容并沒(méi)有取回;后者每一行的后面都多了一個(gè)空行振峻,原因是每行都會(huì)從保持空間取回一行疗绣,追加(大寫(xiě)的G)到模式空間的內(nèi)容之后,以\n分隔铺韧。

2. 使用x命令交換空間

$ sed'x'text121122111

命令執(zhí)行后多矮,發(fā)現(xiàn)前面多了一個(gè)空行并且最后一行不見(jiàn)了。我在前面一直強(qiáng)調(diào)sed命令用好哈打,要有用大腦回顧命令執(zhí)行過(guò)程的能力:

* 當(dāng)讀入第一行的時(shí)候塔逃,模式空間中的內(nèi)容是第一行的內(nèi)容,而保持空間是空的料仗,這個(gè)時(shí)候交換兩個(gè)空間湾盗,導(dǎo)致模式空間為空,保持空間為第一行的內(nèi)容立轧,因此輸出為空行格粪;

* 當(dāng)讀入下一行之后,模式空間為第2行的內(nèi)容氛改,保持空間為第一行的內(nèi)容帐萎,交換后輸出第1行的內(nèi)容;

* 依次讀入每一行胜卤,輸出上一行的內(nèi)容疆导;

* 直到最后一行被讀入到模式空間,交換后輸出倒數(shù)第二行的內(nèi)容葛躏,而最后一行的內(nèi)容并沒(méi)有輸出澈段,此時(shí)命令執(zhí)行結(jié)束。

深入使用

上面的例子簡(jiǎn)單地介紹了保持空間命令的基本使用方法舰攒,這些命令單個(gè)使用可能效果不大败富,但是組合起來(lái)的效果是非常好的。

1.第一個(gè)例子: 使用逗號(hào)拼接行

$ sed'H;$!d;${x;s/^\n//;s/\n/,/g}'text1,11,2,11,22,111,222

上面的命令執(zhí)行過(guò)程是這樣的摩窃,使用H將每一行都追加到保持空間兽叮,這里利用d命令打斷常規(guī)的命令執(zhí)行流程,讓sed繼續(xù)讀入新的一行,直接到將最后一行都放到保持空間充择。這個(gè)時(shí)候使用x命令將保持空間的內(nèi)容交換到模式空間德玫,模式空間的內(nèi)容現(xiàn)在是這樣的:\n1\n11\n2\n11\n22\n111\n222匪蟀。替換的步驟分成兩個(gè)椎麦,首先去掉首個(gè)回車符,然后把剩余的回車符替換成逗號(hào)材彪。

其實(shí)上面的過(guò)程可以包裝成一個(gè)常用的函數(shù):

$functionjoin_lines()>{>sed'H;$!d;${x;s/^\n//;s/\n/,/g}'$1>}$ join_lines text1,11,2,11,22,111,222

進(jìn)一步观挎,我們可以讓分隔符可以通過(guò)參數(shù)設(shè)置,另外一方面刪除文件名的參數(shù)段化,而改成常見(jiàn)的過(guò)濾器命令形式(即通過(guò)管道傳遞輸入):

$functionjoin_lines()>{>localdelim=${1:-,}>sed'H;$!d;${x;s/^\n//;s/\n/'$delim'/g}'>}$ cat text|join_lines';'1;11;2;11;22;111;222

但是如果我們要用&作為符號(hào)嘁捷,就會(huì)出現(xiàn)問(wèn)題:

$ cat text|join_lines'&'11121122111222

上面并沒(méi)有&作為分隔符,這是因?yàn)?amp;是元字符显熏,表示匹配的部分雄嚣,這里剛好是回車符\n。因此我們需要對(duì)分隔符進(jìn)行轉(zhuǎn)義:

$functionjoin_lines()>{>localdelim=${1:-,}>sed'H;$!d;${x;s/^\n//;s/\n/\'$delim'/g}'

> }

$ cat text | join_lines '&'

1&11&2&11&22&111&222

2.第二個(gè)例子:將語(yǔ)句中的特定單詞轉(zhuǎn)換成大寫(xiě)

現(xiàn)在有這樣的文本喘蟆,有許多類似這樣的find the Match statement語(yǔ)句缓升,其中Match是語(yǔ)句的名稱,但是這個(gè)單詞的大小寫(xiě)不統(tǒng)一蕴轨,有些地方是小寫(xiě)的港谊,有些地方是首字符大寫(xiě),現(xiàn)在我們要做的是把這個(gè)單詞統(tǒng)一轉(zhuǎn)換成大寫(xiě)橙弱。

容易聯(lián)想到的是Sed&awk筆記之sed篇:基礎(chǔ)命令中介紹的y命令歧寺,利用y命令確實(shí)可以做到小寫(xiě)轉(zhuǎn)換成大寫(xiě),轉(zhuǎn)換的命令是這樣的:

y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/

但是y命令是會(huì)把模式空間的所有內(nèi)容都轉(zhuǎn)換棘脐,這樣不能滿足我們的需求斜筐。但是我們可以利用保持空間保存當(dāng)前行,然后處理模式空間中的內(nèi)容:

/the.*statement/{h

s/.*the \(.*\) statement.*/\1/y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/G

s/\(.*\)\n\(.*the \).*\( statement.*\)/\2\1\3/}

老規(guī)矩一條一條過(guò)上面的命令蛀缝,為了方便說(shuō)明奴艾,每個(gè)命令解釋后我都會(huì)給出當(dāng)前模式空間和保持空間的內(nèi)容。

首先找到需要處理的行(假設(shè)當(dāng)前行為find the Match statement)内斯。

Pattern space: find the Match statement

將當(dāng)前行保存到保持空間:

Pattern space: find the Match statement

Hold space: find the Match statement

然后利用替換命令獲取需要處理的單詞:

Pattern space: Match

Hold space: find the Match statement

然后通過(guò)轉(zhuǎn)換命令將其轉(zhuǎn)換成大寫(xiě):

Pattern space: MATCH

Hold space: find the Match statement

現(xiàn)在再利用G命令將保持空間的內(nèi)容追加到模式空間最后:

Pattern space: MATCH\nfind the Match statement

Hold space: find the Match statement

最后再次利用替換命令處理下:

Pattern space: find the MATCH statement

Hold space: find the Match statement

流程控制

一般情況下蕴潦,sed是將編輯命令從上到下依次應(yīng)用到讀入的行上,但是像d/n/D/N命令都能夠在一定程度上改變默認(rèn)的執(zhí)行流程俘闯,甚至利用N/D/P三個(gè)命令可以形成一個(gè)強(qiáng)大的循環(huán)處理流程潭苞。除此之外,其實(shí)sed還提供了分支命令(b)和測(cè)試(test)兩個(gè)命令來(lái)控制流程真朗,這兩個(gè)命令可以跳轉(zhuǎn)到指定的標(biāo)簽(label)位置繼續(xù)執(zhí)行命令此疹。標(biāo)簽是以冒號(hào)開(kāi)頭的標(biāo)記,如下例中的:top標(biāo)簽:

:top

command1

command2/pattern/b top

command3

當(dāng)執(zhí)行到/pattern/b top時(shí),如果匹配pattern蝗碎,則跳轉(zhuǎn)到:top標(biāo)簽所在的位置湖笨,繼續(xù)執(zhí)行下一個(gè)命令command1。

如果沒(méi)有指定標(biāo)簽蹦骑,則將控制轉(zhuǎn)移到腳本的結(jié)尾處慈省。也許這只是一個(gè)默認(rèn)的行為,但是有時(shí)候如果用得好也是非常有用的眠菇,例如:

/pattern/b

command1command2command3

當(dāng)執(zhí)行到/pattern/b時(shí)边败,如果匹配pattern,則跳轉(zhuǎn)到最后捎废。這種情況下匹配pattern的行可以避開(kāi)執(zhí)行后續(xù)的命令笑窜,被排除在外。

下一個(gè)例子中登疗,我們利用分支命令的跳轉(zhuǎn)效果達(dá)到類似if語(yǔ)句的效果:

command1/pattern/b end

command2:end

command3

當(dāng)執(zhí)行到/pattern/b end時(shí)排截,如果匹配pattern,則跳轉(zhuǎn)到:end標(biāo)簽所在的位置辐益,跳過(guò)command2而不執(zhí)行断傲。

進(jìn)一步地,利用兩個(gè)分支命令可以達(dá)到if..else的分支效果:

command1/pattern/b dothree

command2

b:dothree

command3

這個(gè)例子中荷腊,當(dāng)執(zhí)行到/pattern/b dothree時(shí)艳悔,若匹配pattern則中轉(zhuǎn)到:dothree標(biāo)簽,此時(shí)執(zhí)行command3女仰;若不匹配猜年,則執(zhí)行command2,并且跳轉(zhuǎn)到最后疾忍。

上面的例子都是用到了分支命令乔外,分支命令的跳轉(zhuǎn)是無(wú)條件的。而與之相對(duì)的是測(cè)試命令一罩,測(cè)試命令的跳轉(zhuǎn)是有條件的杨幼,當(dāng)且僅當(dāng)當(dāng)前行發(fā)生成功的替換時(shí)才跳轉(zhuǎn)。

為了說(shuō)明測(cè)試命令的用法聂渊,我們用它來(lái)實(shí)現(xiàn)前文定義過(guò)的join_lines函數(shù):

$ sed':a;$!N;s/\n/,/;ta'text1,11,2,11,22,111,222

在最前面我們添加了一個(gè)標(biāo)簽:a差购,然后在再最后面利用測(cè)試命令跳轉(zhuǎn)到該標(biāo)簽『核裕可能欲逃,你會(huì)覺(jué)得這里也可以用分支命令,但是事實(shí)上分支命令會(huì)導(dǎo)致死循環(huán)饼暑,因?yàn)樵谒锼麤](méi)有結(jié)束的條件稳析。

但是測(cè)試命令就不同了洗做,這一點(diǎn)直到最后才體現(xiàn)出來(lái)。當(dāng)最后一行被N命令讀入之后彰居,回車替換成逗號(hào)诚纸,此時(shí)ta繼續(xù)跳轉(zhuǎn)到最開(kāi)頭,因?yàn)樗行卸家呀?jīng)被讀入陈惰,所以$!不匹配畦徘,同時(shí)模式空間中的回車已經(jīng)全部被替換成逗號(hào),所以替換也不會(huì)發(fā)生奴潘。之前我們說(shuō)過(guò)旧烧,當(dāng)且僅當(dāng)當(dāng)前行發(fā)生成功的替換時(shí)測(cè)試命令才跳轉(zhuǎn)影钉。所以此時(shí)跳轉(zhuǎn)不會(huì)發(fā)生画髓,退出sed命令。

我們可以利用sedsed這個(gè)工具來(lái)驗(yàn)證上面的過(guò)程平委,sedsed可以用來(lái)調(diào)試sed腳本奈虾。

$./sedsed-d-e':a;$!N;s/\n/,/;ta'text

PATT:1$

HOLD:$

COMM::a

COMM:$!N

PATT:1\n11$

HOLD:$

COMM:s/\n/,/PATT:1,11$

HOLD:$

COMM:t a

COMM:$!N

PATT:1,11\n2$

HOLD:$......COMM:$!N

PATT:1,11,2,11,22,111,222\n1111$

HOLD:$

COMM:s/\n/,/PATT:1,11,2,11,22,111,222,1111$

HOLD:$

COMM:t a

COMM:$!N

PATT:1,11,2,11,22,111,222,1111$

HOLD:$

COMM:s/\n/,/PATT:1,11,2,11,22,111,222,1111$

HOLD:$

COMM:t a

PATT:1,11,2,11,22,111,222,1111$

HOLD:$1,11,2,11,22,111,222,1111

看第27行替換命令發(fā)生的時(shí)候,此時(shí)模式空間的內(nèi)容為PATT:1,11,2,11,22,111,222,1111$廉赔,因此替換失敗肉微,ta命令不會(huì)發(fā)生跳轉(zhuǎn),腳本執(zhí)行退出蜡塌。

而如果在這里把測(cè)試命令換成分支命令碉纳,整個(gè)執(zhí)行過(guò)程就會(huì)陷入死循環(huán)了:

COMM:b a

COMM:$!N

PATT:1,11,2,11,22,111,222,1111$

HOLD:$

COMM:s/\n/,/PATT:1,11,2,11,22,111,222,1111$

HOLD:$

COMM:b a

COMM:$!N

PATT:1,11,2,11,22,111,222,1111$

高級(jí)命令總結(jié)

到此為止,所有高級(jí)命令的用法就已經(jīng)介紹完了馏艾。最后一段內(nèi)容由于時(shí)間的關(guān)系劳曹,寫(xiě)得比較倉(cāng)促。高級(jí)命令的用法比起基礎(chǔ)命令相對(duì)復(fù)雜一點(diǎn)琅摩,而且容易出錯(cuò)铁孵,需要十分小心,如果不確定可以用上面介紹的sedsed工具來(lái)調(diào)式下房资,而且便于加深各種命令行為的理解蜕劝。

轉(zhuǎn)自:團(tuán)子的小窩, 本文固定鏈接:Sed and awk 筆記之 sed 篇:高級(jí)命令(二)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市轰异,隨后出現(xiàn)的幾起案子岖沛,更是在濱河造成了極大的恐慌,老刑警劉巖搭独,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件婴削,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡戳稽,警方通過(guò)查閱死者的電腦和手機(jī)馆蠕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門期升,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人互躬,你說(shuō)我怎么就攤上這事播赁。” “怎么了吼渡?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵容为,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我寺酪,道長(zhǎng)坎背,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任寄雀,我火速辦了婚禮得滤,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘盒犹。我一直安慰自己懂更,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布急膀。 她就那樣靜靜地躺著沮协,像睡著了一般。 火紅的嫁衣襯著肌膚如雪卓嫂。 梳的紋絲不亂的頭發(fā)上慷暂,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音晨雳,去河邊找鬼行瑞。 笑死,一個(gè)胖子當(dāng)著我的面吹牛悍募,可吹牛的內(nèi)容都是我干的蘑辑。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼坠宴,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼洋魂!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起喜鼓,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤副砍,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后庄岖,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體豁翎,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年隅忿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了心剥。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邦尊。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖优烧,靈堂內(nèi)的尸體忽然破棺而出蝉揍,到底是詐尸還是另有隱情,我是刑警寧澤畦娄,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布又沾,位于F島的核電站,受9級(jí)特大地震影響熙卡,放射性物質(zhì)發(fā)生泄漏杖刷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一驳癌、第九天 我趴在偏房一處隱蔽的房頂上張望滑燃。 院中可真熱鬧,春花似錦喂柒、人聲如沸不瓶。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至熙参,卻和暖如春艳吠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背孽椰。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工昭娩, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人黍匾。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓栏渺,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親锐涯。 傳聞我的和親對(duì)象是個(gè)殘疾皇子磕诊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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