《Sed 和 Awk》(第二版)學習系列之第六章

 

第六章  高級sed命令

 

1.     高級命令主要分成3組:

(1)    處理多行模式空間(N, D, P)

(2)    採用保持空間來保存模式空間中的內容並使它可用於後續的命令(H, h, G, g, x)

(3)    編寫使用分支和條件指令的腳本來更改控制流(:, b, t)

1.     多行模式空間:

(1)    追加下一行(N): 多行命令通過讀取新的輸入行,並將其添加到模式空間的現有內容之後來創建多行模式空間,模式空間最初的內容和新的輸入行之間用換行符分割,在模式空間中嵌入的換行符可以通過轉義字符\n來匹配,在多行模式空間中,元字符^匹配模式空間中的第一個字符,而不匹配換行符後面的字符,同樣,$只匹配模式空間中最後的換行符,而不匹配任何嵌入的換行符,在執行Next(N)命令後,控制將被傳遞給腳本中的後續命令,與next(n)命令不同的是,next輸出模式空間的內容,然後讀取新的一行。

(2)    多行刪除(D): 刪除命令d刪除模式空間中的內容並自動讀取新的輸入行,從而在腳本的頂端重新使用編輯方法,D刪除命令稍微有些不同,它刪除的是模式空間中直到第一個嵌入的換行符的這部分內容(可以看到,基本上D刪除命令只是刪除多行中的第一行),另外,它不會導致讀入新的輸入行,並且它返回的是腳本的頂端

【舉例】

測試文件:

刪除命令組:

測試結果:

【解釋】首先,一定要理解“模式空間是以^符號開始,並以$符號結束的”這句話,“^\n$”實際上匹配的是兩個空行。因此,原命令組的含義是先定位每個空行,然後追加每個空行的下一行,若這兩個時空行,則刪除之,否則,跳過。若將刪除命令換成D,則結果將不同,這是因爲當遇到兩個空行時,則會首先刪除第一個空行,並在下次遍歷腳本時,將下一行進行讀入,若這行是空白的,則將會繼續刪除,否則一起輸出。這正是當有多行空格時,依然最後只保留一個空格的原因。

(3)多行打印命令(P):多行打印命令與p命令的差別在於,該命令只是輸出多行模式空間的第一部分,直到第一個嵌入的換行符爲止,在執行完腳本的最後一個命令後,模式空間的內容會自動輸出(可以使用-n選項進行抑制),

     ♥ P命令經常出現在N之後和D之前,這三個命令可以形成一個輸入/輸出循環,用來維護兩行的模式空間,但是一次只能輸出一行,然後返回到腳本的頂端將所有的命令應用於模式空間的第二行

       ♥ 對P輸出的理解可參考前面的多行刪除命令D.

       ♥ 實例分析:

 測試文件:(test)

Here are examples of the UNIX

System.  Where UNIX

System appears, it should be the UNIX

Operating System.

sed腳本:(sed)

/UNIX$/{

N

/\nSystem/{

s// Operating &/

P

D

}

}

/UNIX$/{

N

s/\nSystem/ Operating &/

P

D

}

 結果及其分析:sed –f sed test

Here are examples of the UNIX Operating

System.  Where UNIX Operating

System appears, it should be the UNIX

Operating System.

     

【分析】上面的sed腳本有兩個,二者是等價的,作用均是將所匹配的\nSystem替換爲

Operating \nSystem, 注意前面所講的sed中替換的replacement中的幾個特殊符號所代表的含義,&則是代表前面所代表的匹配字符,即“\nSystem”;另外替換中若沒指定地址,則將所匹配的pattern進行替換,在這個地方, s// Operating &/ 表示將所匹配的\nSystem進行替換。

3     包含哪一行:(H,h,G,g)

♥ 保持空間:保持空間是一個預留緩衝區,它可以與模式空間中的內容進行交換,它最常見的用途是,在

改變模式空間中的內容時,用於保留當前輸入行的副本。影響模式空間的命令有:

【注意】大小寫命令之間的區別是:小寫命令直接改寫目的緩存區的內容,而大寫命令則是追加緩存

區的現有內容。Hold命令會在保持空間的內容之後放置一個換行符,然後後面跟隨模式空間的內容,

儘管保持空間中的內容可能會是空的;Get命令在模式空間的內容之後放置一個換行符,然後後面跟

隨保持空間的內容。交換命令則用來交換兩個緩存區的內容,這對兩個緩存區是沒有任何副作用的。

♥ 實例分析:

  測試文件:

find the Match statement

Consult the Get statement.

using the Read statement to retrieve data

  sed腳本:

/the .* statement/{

h

s/.*the \(.*\) statement.*/\1/

y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/

G

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

}

結果與分析:sed –f sed test

  【分析】這個腳本的主要功能是將the與statement之間的單詞全部轉換成大寫字母,如果單純用前面的轉換命令(y),是不能實現這個功能的,因爲轉換命令所施作用對象是所有行,必須藉助保持空間與模式空間中的緩存交換來實現。

h

pattern space: find the Match statement

hold space: find the Match statement

s/.*the \(.*\) statement.*/\1/

pattern space: Match

hold space: find the Match statement

y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/

pattern space: MATCH

hold space: find the Match statement

G(追加,另外加上換行符)

pattern space: MATCH\nfind the Match statement

hold space: find the Match statement

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

pattern space: find the MATCH statement

hold space: find the Match statement

上面是所匹配的第一行經歷腳本之後,模式空間和保持空間中剩餘的內容,在此需要解釋的是:

替換命令中的\n所代表的含義,它是用來匹配第n個字串,這個字串之前在pattern中用\(和\)指定,因此這個命令類似於“抓取”的功能,只是把整行中某一部分抽取出來。另外注意在書寫腳本時,不要忘記字符之間隱藏的空格。

4.    高級的流控制命令:分支(b),測試(t)

(1) 分支和測試命令將腳本中的控制轉移到指定的標籤行。若沒有指定標籤,則將控制轉移到腳本的結尾

處,其中分支命令是無條件轉移,測試命令用於有條件轉移,它只有當轉換命令改變時纔會執行

標籤是任意不多於7個字符的序列,標籤本身佔據一行並以冒號開始

:mylable --------------------------中間不能有空格

b mylable ---------------------------命令和標籤之間有空格,但不能在標籤後面再插入空格

(2) 分支命令用於在腳本中將控制權轉移到另一行

[address]b[label] ----------label是可選的,若沒有,則跳至腳本結尾處,否則,調至標籤後面

分支命令可以用來構造選擇和循環過程:

(循環)

 

 (選擇,命令1和2只能選其一)

(選擇,命令2和3選其一)

(3) 若在當前匹配地址的行上進行成功替換,則test命令就轉到標籤處,若沒有,轉到結尾處,實際上實現了條件功能。

5. 綜合實例:

   跨行查找短語(可能中間出現斷裂而出現在不同的行):

#! /bin/sh

# phrase -- search for words across lines

# $1 = search string; remaining args = filenames

search=$1

shift

for file

do

sed '

/'"$search"'/b   --------------------第一行出現匹配短語,直接退出並打印

N

h

s/.*\n//   -----------------------只保留第二行,並將前兩行存放到保持空間

/'"$search"'/b  ----------------第二行出現匹配短語,直接退出打印

g

s/  *\n/  /   -----------------------將前兩行組成一個整體,爲後面的檢測做準備

/'"$search"'/{

g

b

}   ----------------------------------若整體行出現匹配短語,則將兩行同時打印出來

g

D' $file   -------------------------------防止出現跨行匹配,刪除第一行,保留第二行,控制轉移到頂端

done

【注意】這個腳本有個缺陷,總會打印出源test文本中最後一行字符串!

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章