運維工作中sed常規操作命令梳理

散盡浮華發表於2016-10-11

 

sed是一個流編輯器(stream editor),一個非互動式的行編輯器。它一次處理一行內容。處理時,把當前處理的行儲存在臨時緩衝區中,稱為“模式空間”,接著用sed命令處理緩衝區中的內容,處理完成後,把緩衝區的內容送往螢幕;接著處理下一行,這樣不斷重複,直到檔案末尾。檔案內容並沒有改變,除非你使用重定向儲存輸出。sed主要用來自動編輯一個或多個檔案;簡化對檔案的反覆操作;編寫轉換程式等。在日常的運維工程中,會時常用sed命令來處理行操作,下面根據工作中的使用經驗對sed的用法做一梳理:

sed(stream editor)特徵:
1)流線型,非互動式的編輯器。它每次只處理一行檔案並把輸出列印到螢幕上。
2)模式空間(Pattern space)即存放當前正在處理的行的快取空間。 一旦處理工作完成,sed就會把結果輸出到螢幕,然後清空模式空間並把下一行讀入模式空間,進行相關處理;直到最後一行。
3)sed是無破壞性的,它可以不更改原檔案,除非使用重定向儲存輸出結果或者使用特定生效引數(比如-i)。
4)對於一行文字,sed命令是依次執行的,如果有多個命令的話。這時,要注意各命令之間可能產生的相互影響。
5)對於多個sed命令,我們可以用“{}”把它們括起來。但要注意,右花括號一定要單獨成行。
6)可以把一系列的sed命令寫入檔案中並用sed的-f選項呼叫

sed的語法及定址方式:
語法:
sed [options] 'command' filename(s)
定址方式:
1)單行定址:[line-address]command;尋找匹配line-address的行並進行處理。
2)行集合定址:[regexp]command ;匹配檔案中的一行或多行,如/^A/command匹配所有以A開頭的行。
3)多行定址: [line-address1,line-address2] command;尋找在兩個地址之間的內容並做相應的處理。
4)巢狀定址:10,20{
/^$/d
#上面三種定址方法都可以應用在這裡

sed選項

sed的相關命令:

替換標誌:

sed支援的一些元字元:

----------------------------------------------------------------------------------------------------------------------------
sed -n 'ap' filename 列印第a行
sed -n 'a,mp' filename 列印第a到m行
sed -n 'ap;mp' filename 列印第a行和第m行
sed -n '/wang/p' filename 列印包含wang字元的行
sed -n '3,$p' filename 列印第3到最後一行

sed -i 'nd' filename 刪除第n行
sed -i 'n,md' filename 刪除第n到m行
sed -i 'nd;md' filename 刪除第n行和第m行
sed -i '/wang/d' filename 刪除包含wang字元的行
sed -i '3,$d' filename 刪除第3到最後一行

sed -i 's/a/b/g' filename 將a替換成b,全文替換
sed -i 'ns/a/b/g' filename 將第行中的a替換成b
sed -i 'n,ms/a/b/g' filename 將第n到m行中的a替換成b
sed -i 'ns;ms/a/b/g' filename 將第n行和第m行中的a替換成b
sed -i '3,$s/a/b/g' filename 將第3到最後一行中的a替換成b
sed -i '/wang/s/a/b/g' filename 將包含wang字元的行中的a替換成b

sed的替換命令格式有三種:
1)s/A/B/g
2) s#A#B#g
3) s_A_B_g
g表示全域性替換
例如:
將php.ini檔案中的/Data/app/php5.5.1/lib/php/extensions/no-debug-non-zts-20121212/替換成/Data/app/php5.6.26/lib/php/extensions/no-debug-non-zts-20131226/
# sed -i 's#/Data/app/php5.5.1/lib/php/extensions/no-debug-non-zts-20121212/#/Data/app/php5.6.26/lib/php/extensions/no-debug-non-zts-20131226/#g' php.ini
----------------------------------------------------------------------------------------------------------------------------

sed常用到的幾個選項與引數解釋:
-n :使用安靜(silent)模式。在一般 sed 的用法中,所有來自 STDIN 的資料一般都會被列出到終端上。但如果加上 -n 引數後,則只有經過sed 特殊處理的那一行(或者動作)才會被列出來。
-e :直接在命令列模式上進行 sed 的動作編輯;(加多個-e,表示可以多點編輯)
-f :直接將 sed 的動作寫在一個檔案內, -f filename 則可以執行 filename 內的 sed 動作;
-r :sed 的動作支援的是延伸型正規表示法的語法。(預設是基礎正規表示法語法)
-i :直接修改讀取的檔案內容,而不是輸出到終端。(這個很關鍵!)
動作說明:
a :新增, a 的後面可以接字串,而這些字串會在新的一行出現(目前的下一行);
c :取代, c 的後面可以接字串,這些字串可以取代 多行 之間的內容;
d :刪除,因為是刪除啊,所以 d 後面通常不接任何內容;
i :插入, i 的後面可以接字串,而這些字串會在新的一行出現(目前的上一行);
p :列印,亦即將某個選擇的資料印出。通常 p 會與引數 sed -n 一起執行;
s :取代,可以直接進行取代的工作。通常這個 s 的動作可以搭配正規表示法;例如 sed -i '1,20s/old/new/g' filename 將第1行到20行的old替換為new

要注意的是,sed 後面接的動作,最好以''單引號括住。當然用""雙引號也可以。
如果使用單引號,那麼就沒辦法通過\’這樣來轉義,就有雙引號就可以了,在雙引號內可以用\”來轉義。

下面通過例項說明sed的用法:
1)以行為單位的新增/刪除
將 /etc/passwd 的內容列出並且列印行號,同時,請將第 2~5 行刪除!
[root@www ~]# cat /etc/passwd | sed '2,5d'

只要刪除第2行
[root@www ~]# cat /etc/passwd | sed '2d'

要刪除第3到最後一行
[root@www ~]# cat /etc/passwd | sed '3,$d'

在第二行後(亦即是加在第三行)加上drink tea字樣!
[root@www ~]# cat /etc/passwd | sed '2a drink tea'

那如果是要在第二行前新增
[root@www ~]# cat /etc/passwd | sed '2i drink tea'

在匹配root的行的前面新增extension="huanqiu"
(-i參數列示直接在檔案裡新增,而不是僅僅在終端輸出裡新增)
[root@www ~]# cat /etc/passwd | sed -i '/root/i extension="huanqiu"'

如果是要增加兩行以上,在第二行後面加入兩行字,例如『Drink tea or .....』與『drink beer?』
[root@www ~]# cat /etc/passwd | sed '2a Drink tea or ......\                //回車,新增第二行內容,每行之間用\隔開
> drink beer ?'
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
Drink tea or ......
drink beer ?
注意:
每一行之間都必須要以反斜槓『 \ 』來進行新行的新增!
所以,上面的例子中,我們可以發現在第一行的最後面就有 \ 存在。

新增多行內容如下:

新增多行內容如下:
[root@www ~]# cat /etc/passwd | sed '2a Drink tea or ......\
> drink beer ?\
> wangshibo\
> hahaha'
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
Drink tea or ......
drink beer ?
wangshibo
hahaha

如果多行之間不加\隔開,那麼就預設加到一行:
[root@www ~]# cat /etc/passwd | sed '2a Drink tea or ...... wangshibo'
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
Drink tea or ...... wangshibo

2)以行為單位的替換與顯示
將第2-5行的內容取代成為『No 2-5 number』
[root@www ~]# cat /etc/passwd | sed '2,5c No 2-5 number'
透過這個方法我們就能夠將資料整行取代了!

僅列出 /etc/passwd 檔案內的第 5-7 行
[root@www ~]# cat /etc/passwd | sed -n '5,7p'
可以透過這個 sed 的以行為單位的顯示功能, 就能夠將某一個檔案內的某些行號選擇出來顯示

3)資料的搜尋並顯示
搜尋 /etc/passwd有root關鍵字的行
[root@www ~]# cat /etc/passwd | sed '/root/p'
如果root找到,除了輸出所有行,還會輸出匹配行。

使用-n的時候將只列印包含模板的行。
[root@www ~]# cat /etc/passwd | sed -n '/root/p'

4)資料的搜尋並刪除
刪除/etc/passwd所有包含root的行,其他行輸出
[root@www ~]# cat /etc/passwd | sed '/root/d'

5)資料的搜尋並執行命令
找到匹配模式eastern的行後,執行後面花括號中的一組命令,每個命令之間用分號分隔。
下面表示搜尋匹配root的行後,把bash替換為blueshell,再輸出這行:
[root@www ~]# cat /etc/passwd | sed -n '/root/{s/bash/blueshell/;p}'
1 root:x:0:0:root:/root:/bin/blueshell
如果只替換/etc/passwd的第一個bash關鍵字為blueshell,就退出

[root@www ~]# cat /etc/passwd | sed -n '/bash/{s/bash/blueshell/;p;q}'
1 root:x:0:0:root:/root:/bin/blueshell
最後的q是退出。

6)資料的搜尋並替換
除了整行的處理模式之外,sed 還可以用行為單位進行部分資料的搜尋並取代。基本上sed的搜尋與替代的與vi相當的類似!
它有點像這樣:
sed 's/要被取代的字串/新的字串/g'

先觀察原始資訊,利用 /sbin/ifconfig 查詢 IP
[root@www ~]# /sbin/ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:90:CC:A6:34:84
inet addr:192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::290:ccff:fea6:3484/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

將 IP 前面的部分予以刪除
[root@www ~]# /sbin/ifconfig eth0 | grep 'inet addr' | sed 's/^.*addr://g'
192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0

接下來則是刪除後續的部分,亦即: 192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0
將 IP 後面的部分予以刪除
[root@www ~]# /sbin/ifconfig eth0 | grep 'inet addr' | sed 's/^.*addr://g' | sed 's/Bcast.*$//g'
192.168.1.100

7)多點編輯(-e引數)
一條sed命令,刪除/etc/passwd第三行到末尾的資料,並把bash替換為blueshell
[root@www ~]# cat /etc/passwd | sed -e '3,$d' -e 's/bash/blueshell/'
1 root:x:0:0:root:/root:/bin/blueshell
2 daemon:x:1:1:daemon:/usr/sbin:/bin/sh
-e表示多點編輯,第一個編輯命令刪除/etc/passwd第三行到末尾的資料,第二條命令搜尋bash替換為blueshell。

8)直接修改檔案內容(危險動作)
sed 可以直接修改檔案的內容,不必使用管道命令或資料流重導向!
不過,由於這個動作會直接修改到原始的檔案,所以請你千萬不要隨便拿系統配置來測試! 我們還是使用下載的 regular_express.txt 檔案來測試看看吧!

利用sed將regular_express.txt 內每一行結尾若為 . 則換成 !
[root@www ~]# sed -i 's/\.$/\!/g' regular_express.txt

利用sed直接在 regular_express.txt 最後一行加入『# This is a test』
[root@www ~]# sed -i '$a # This is a test' regular_express.txt

由於$代表的是最後一行,而a的動作是新增,因此該檔案最後新增『# This is a test』

sed的-i選項表示:可以直接修改檔案內容,這功能非常有幫助!
舉例來說,如果你有一個 100 萬行的檔案,你要在第 100 行加某些文字,此時使用 vim 可能會瘋掉!因為檔案太大了!
這個時候就可以利用sed了,非常高效方面!!透過sed直接修改/取代的功能,甚至不需要使用vim去修訂了!

----------------------------------------------------------------------------------------------------------------------
以下是經常用到的一些sed操作
[root@www ~]# sed -e 's/123/1234/' a.txt
將a.txt檔案中所有行中的123用1234替換(-e表示命令以命令列的方式執行;引數s,表示執行替換操作)

[root@www ~]# sed -e '3,5 a4' a.txt
將a.txt檔案中的3行到5行之間所有行的後面新增一行內容為4的行(引數a,表示新增行,引數a後面指定新增的內容)

[root@www ~]# sed -e '1s/12/45/' a.txt
把第一行的12替換成45(-e參數列示輸出結果到當前終端下,即只在輸出的結果中替換,其實檔案裡並沒有真實生效;要使檔案中的替換生效,需使用-i引數)

[root@www ~]# sed -i "s/oldstring/newstring/g" `grep oldstring -rl yourdir`
批量處理通過grep搜尋出來的所有文件,將這些文件中所有的oldstring用newstring替換(-i參數列示直接對目標檔案操作)

[root@www ~]# sed -n 's/^test/mytest/p' example.file
(-n)選項和p標誌一起使用表示只列印那些發生替換的行。也就是說,如果某一行開頭的test被替換成mytest,就列印它。(^這是正規表示式中表示開頭,該符號後面跟的就是開頭的字串)(引數p表示列印行)

[root@www ~]# sed 's/^wangpan/&19850715/' example.file
表示被替換換字串被找到後,被替換的字串通過&符號連線給出的字串組成新字元傳替換被替換的字串,所有以wangpan開頭的行都會被替換成它自已加19850715,變成wangpan19850715

[root@www ~]# sed -n 's/\(love\)able/\1rs/p' example.file
love被標記為1,所有loveable會被替換成lovers,而且替換的行會被列印出來。需要將這條命令分解,s/是表示替換操作,\(love\)表示選中love字串,\(love\)able/表示包含loveable的行,\(love\)able/\l表示love字串標記為1,表示在替換過程中不變。rs/表示替換的目標字串。這條命令的操作含義:只列印替換了的行

[root@www ~]# sed 's[root@www ~]#10[root@www ~]#100[root@www ~]#g' example.file
不論什麼字元,緊跟著s命令的都被認為是新的分隔符,所以,“[root@www ~]#”在這裡是分隔符,代替了預設的“/”分隔符。表示把所有10替換成100。

[root@www ~]# sed -n '/love/,/unlove/p' example.file
只列印包含love字串行到包含unlove字串行之間的所有行(確定行的範圍就是通過逗號實現的)

[root@www ~]# sed -n '5,/^wang/p' example
只列印從第五行開始到第一個包含以wang開始的行之間的所有行

[root@www ~]# sed '/love/,/unlove/s/[root@www ~]#/wangpan/' example.file
對於包含love字串的行到包含unlove字串之間的行,每行的末尾用字串wangpan替換。
字串[root@www ~]#/表示以字串結尾的行,[root@www ~]#/表示每一行的結尾,s/[root@www ~]#/wangpan/表示每一行的結尾新增wangpan字串

[root@www ~]# sed -e '11,53d' -e 's/wang/pan/' example.file
(-e)選項允許在同一行裡執行多條命令。如例子所示,第一條命令刪除11至53行,第二條命令用pan替換wang。命令的執行順序對結果有影響。如果兩個命令都是替換命令,那麼第一個替換命令將影響第二個替換命令的結果。(引數d,表示刪除指定的行)

[root@www ~]# sed --expression='s/wang/pan/' --expression='/love/d' example.file
一個比-e更好的命令是--expression。它能給sed表示式賦值。

[root@www ~]# sed '/wangpan/r file' example.file
file裡的內容被讀進來,顯示在與wangpan匹配的行後面,如果匹配多行,則file的內容將顯示在所有匹配行的下面。引數r,表示讀出檔案,後面空格緊跟檔名稱

[root@www ~]# sed -n '/test/w file' example.file
在example.file中所有包含test的行都被寫入file裡。引數w,表示將匹配的行寫入到指定的檔案file中

[root@www ~]# sed '/^test/a\oh! My god!' example.file
'oh! My god!'被追加到以test開頭的行的後面,sed要求引數a後面有一個反斜槓。

[root@www ~]# sed '/test/i\oh! My god!' example.file
'oh! My god!'被追加到包含test字串行的前面,引數i表示新增指定內容到匹配行的前面,sed要求引數i後面有一個反斜槓

[root@www ~]# sed '/test/{ n; s/aa/bb/; }' example.file
如果test被匹配,則移動到匹配行的下一行,替換這一行的aa,變為bb。引數n,表示讀取匹配行的下一個輸入行,用下一個命令處理新的行而不是匹配行。Sed要求引數n後跟分號

[root@www ~]# sed '1,10y/abcde/ABCDE/' example.file
把1—10行內所有abcde轉變為大寫,注意,正規表示式元字元不能使用這個命令。引數y,表示把一個字元翻譯為另外的字元(但是不用於正規表示式)

[root@www ~]# sed -i 's/now/right now/g' test_sed_command.txt

表示直接操作檔案test_sed_command.txt,將檔案test_sed_command.txt中所有的now用right now替換。引數-i,表示直接操作修改檔案,不輸出。
[root@www ~]# sed '2q' test_sed_command.txt

在列印完第2行後,就直接退出sed。引數q,表示退出
[root@www ~]# sed -e '/old/h' -e '/girl-friend/G' test_sed_command.txt
首先了解引數h,拷貝匹配成功行的內容到記憶體中的緩衝區。在瞭解引數G,獲得記憶體緩衝區的內容,並追加到當前模板塊文字的後面。上面命令列的含義:將包含old字串的行的內容儲存在緩衝區中,然後將緩衝區的內容拿出來新增到包含girl-friend字串行的後面。隱含要求蒐集到緩衝區的匹配行在需要新增行的前面。

[root@www ~]# sed -e '/test/h' -e '/wangpan/x' example.file
將包含test字串的行的內容儲存在緩衝區中,然後再將緩衝區的內容替換包含wangpan字串的行。引數x,表示行替換操作。隱含要求蒐集到緩衝區的匹配行在需要被替換行的前面。

如果sed在列印時不加-n引數,那麼列印多少行,其實就是在多少行下面列印這行內容,如下:
[root@www ~]# cat pets.txt
1111
222
3333
aaaa
bbb
vvvv
[root@www ~]# sed '3p' pets.txt
1111
222
3333
3333
aaaa
bbb
vvvv
[root@www ~]# sed '3p;5p' pets.txt
1111
222
3333
3333
aaaa
bbb
bbb
vvvv

把其中的my字串替換成Hao Chen’s
注意:如果你要使用單引號,那麼你沒辦法通過\’這樣來轉義,就有雙引號就可以了,在雙引號內可以用\”來轉義。
[root@www ~]# sed "s/my/Hao Chen's/g" pets.txt

再注意:上面的sed並沒有對檔案的內容改變,只是把處理過後的內容輸出,如果你要寫回檔案,你可以使用重定向,如:
[root@www ~]# sed "s/my/Hao Chen's/g" pets.txt > pets.txt
或使用 -i 引數直接修改檔案內容:
[root@www ~]# sed -i "s/my/Hao Chen's/g" pets.txt

在每一行最前面加點東西,比如在每一行的前面新增#號或wang字元
[root@www ~]# sed 's/^/#/g' pets.txt
[root@www ~]# sed 's/^/wang/g' pets.txt
[root@www ~]# sed -i 's/^/wang/g' pets.txt //直接在檔案中生效

在每一行最後面加點東西,比如在每一行的後面新增 --- 或者done字元
[root@www ~]# sed 's/$/ --- /g' pets.txt
[root@www ~]# sed 's/$/done/g' pets.txt

順便介紹一下正規表示式的一些最基本的東西:
^ 表示一行的開頭。如:/^#/ 以#開頭的匹配。
[root@www ~]# 表示一行的結尾。如:/}[root@www ~]#/ 以}結尾的匹配
\< 表示詞首。 如 \ 表示詞尾。 如 abc\> 表示以 abc 結尾的詞.
. 表示任何單個字元。
* 表示某個字元出現了0次或多次。
[ ] 字符集合。 如:[abc]表示匹配a或b或c,還有[a-zA-Z]表示匹配所有的26個字元。如果其中有^表示反,如[^a]表示非a的字元

正規則表示式是一些很神奇的事,比如要去掉a.html檔案中的tags:
[root@www ~]# cat a.html
<b>This</b> is what <span style="text-decoration: underline;">I</span> meant. Understand?

如果這樣搞的話,就會有問題
[root@www ~]# sed 's/<.*>//g' a.html
meant. Understand?

要解決上面的那個問題,就得像下面這樣。
其中的'[^>]' 指定了除了>的字元重複0次或多次。
[root@www ~]# sed 's/<[^>]*>//g' a.html
This is what I meant. Understand?

只替換每一行的第一個s:
[root@www ~]# sed 's/s/S/1' my.txt

只替換每一行的第二個s:
[root@www ~]# sed 's/s/S/2' my.txt

只替換第一行的第3個以後的s:
[root@www ~]# sed 's/s/S/3g' my.txt

多個匹配
如果我們需要一次替換多個模式,可參看下面的示例:(第一個模式把第一行到第三行的my替換成your,第二個則把第3行以後的This替換成了That)
[root@www ~]# sed '1,3s/my/your/g; 3,[root@www ~]#s/This/That/g' my.txt
上面的命令等價於:(注:下面使用的是sed的-e命令列引數)
[root@www ~]# sed -e '1,3s/my/your/g' -e '3,[root@www ~]#s/This/That/g' my.txt

可以使用&來當做被匹配的變數,然後可以在基本左右加點東西。如下所示:
[root@www ~]# cat b.txt
This is my cat, my cat's name is betty
This is my dog, my dog's name is frank
This is my fish, my fish's name is george
This is my goat, my goat's name is adam
[root@www ~]# sed 's/my/[&]/g' b.txt
This is [my] cat, [my] cat's name is betty
This is [my] dog, [my] dog's name is frank
This is [my] fish, [my] fish's name is george
This is [my] goat, [my] goat's name is adam

圓括號匹配
使用圓括號匹配的示例:(圓括號括起來的正規表示式所匹配的字串會可以當成變數來使用,sed中使用的是\1,\2…)
[root@www ~]# sed 's/This is my \([^,]*\),.*is \(.*\)/\1:\2/g' b.txt
cat:betty
dog:frank
fish:george
goat:adam

上面這個例子中的正規表示式有點複雜,解開如下(去掉轉義字元):
正則為:This is my ([^,]*),.*is (.*)
匹配為:This is my (cat),……….is (betty)
然後:\1就是cat,\2就是betty

N命令:把下一行的內容納入當成緩衝區做匹配。
下面的的示例會把原文字中的偶數行納入奇數行匹配,而s只匹配並替換一次,所以,就成了下面的結果:
即匹配奇數行的替換,偶數行的不匹配:
[root@www ~]# vim a.txt
[root@www ~]# cat a.txt
This is my cat
my cat's name is betty
This is my dog
my dog's name is frank
This is my fish
my fish's name is george
This is my goat
my goat's name is adam
[root@wutao ~]# sed 'N;s/my/your/' a.txt
This is your cat
my cat's name is betty
This is your dog
my dog's name is frank
This is your fish
my fish's name is george
This is your goat
my goat's name is adam

也就是說,原來的檔案成了:
This is my cat\n my cat's name is betty
This is my dog\n my dog's name is frank
This is my fish\n my fish's name is george
This is my goat\n my goat's name is adam

這樣一來,下面的例子你就明白了,
[root@www ~]# sed 'N;s/\n/,/' a.txt
This is my cat, my cat's name is betty
This is my dog, my dog's name is frank
This is my fish, my fish's name is george
This is my goat, my goat's name is adam

a命令和i命令
a命令就是append, i命令就是insert,它們是用來新增行的
其中的1i表明,其要在第1行前插入一行(insert)
[root@www ~]# cat a.txt
This is my cat
my cat's name is betty
This is my dog
my dog's name is frank
This is my fish
my fish's name is george
This is my goat
my goat's name is adam
[root@www ~]# sed "1 i This is my monkey, my monkey's name is wukong" a.txt
This is my monkey, my monkey's name is wukong
This is my cat
my cat's name is betty
This is my dog
my dog's name is frank
This is my fish
my fish's name is george
This is my goat
my goat's name is adam

其中的1a表明,其要在最後一行後追加一行(append)
[root@www ~]# sed "$ a This is my monkey, my monkey's name is wukong" a.txt
This is my cat
my cat's name is betty
This is my dog
my dog's name is frank
This is my fish
my fish's name is george
This is my goat
my goat's name is adam
This is my monkey, my monkey's name is wukong

可以運用匹配來新增文字:
注意其中的/fish/a,這意思是匹配到/fish/後就追加一行
[root@www~]# sed "/fish/a This is my monkey, my monkey's name is wukong" a.txt
This is my cat
my cat's name is betty
This is my dog
my dog's name is frank
This is my fish
This is my monkey, my monkey's name is wukong
my fish's name is george
This is my monkey, my monkey's name is wukong
This is my goat
my goat's name is adam

下面這個例子是對每一行都挺插入:
[root@www ~]# sed "/my/a ----" a.txt
This is my cat
----
my cat's name is betty
----
This is my dog
----
my dog's name is frank
----
This is my fish
----
my fish's name is george
----
This is my goat
----
my goat's name is adam
----

c命令
c 命令是替換匹配行
[root@www ~]# sed "2 c This is my monkey, my monkey's name is wukong" a.txt
This is my cat
This is my monkey, my monkey's name is wukong
This is my dog
my dog's name is frank
This is my fish
my fish's name is george
This is my goat
my goat's name is adam

[root@www ~]# sed "/fish/c This is my monkey, my monkey's name is wukong" a.txt
This is my cat
my cat's name is betty
This is my dog
my dog's name is frank
This is my monkey, my monkey's name is wukong
This is my monkey, my monkey's name is wukong
This is my goat
my goat's name is adam

d命令
刪除匹配行
從一個模式到另一個模式
[root@www ~]# sed -n '/dog/,/fish/p' my.txt
This is my dog, my dog's name is frank
This is my fish, my fish's name is george

從第一行列印到匹配fish成功的那一行
[root@www ~]# sed -n '1,/fish/p' my.txt
This is my cat, my cat's name is betty
This is my dog, my dog's name is frank
This is my fish, my fish's name is george

sed的Address
第一個是關於address,幾乎上述所有的命令都是這樣的(注:其中的!表示匹配成功後是否執行命令)
[address[,address]][!]{cmd}
address可以是一個數字,也可以是一個模式,你可以通過逗號要分隔兩個address 表示兩個address的區間,參執行命令cmd,虛擬碼如下:

[root@wutao ~]# cat b.txt
This is my cat, my cat's name is betty
This is my dog, my dog's name is frank
This is my fish, my fish's name is george
This is my goat, my goat's name is adam

其中的+3表示後面連續3行
[root@wutao ~]# sed '/dog/,+3s/^/# /g' b.txt
This is my cat, my cat's name is betty
# This is my dog, my dog's name is frank
# This is my fish, my fish's name is george
# This is my goat, my goat's name is adam

sed命令打包
第二個是cmd可以是多個,它們可以用分號分開,可以用大括號括起來作為巢狀命令。下面是幾個例子:
[root@wutao ~]# cat d.txt
This is my cat
my cat's name is betty
This is my dog
my dog's name is frank
This is my fish
my fish's name is george
This is my goat
my goat's name is adam

對3行到第6行,執行命令/This/d
[root@wutao ~]# sed '3,6 {/This/d}' d.txt
This is my cat
my cat's name is betty
my dog's name is frank
my fish's name is george
This is my goat
my goat's name is adam

對3行到第6行,匹配/This/成功後,再匹配/fish/,成功後執行d命令
[root@wutao ~]# sed '3,6 {/This/{/fish/d}}' d.txt
This is my cat
my cat's name is betty
This is my dog
my dog's name is frank
my fish's name is george
This is my goat
my goat's name is adam

從第一行到最後一行,如果匹配到This,則刪除之;如果前面有空格,則去除空格
[root@wutao ~]# sed '1,${/This/d;s/^ *//g}' d.txt
my cat's name is betty
my dog's name is frank
my fish's name is george
my goat's name is adam

sed的Hold Space
需要先了解一下Hold Space的概念,先來看四個命令:
g:將hold space中的內容拷貝到pattern space中,原來pattern space裡的內容清除
G:將hold space中的內容append到pattern space\n後
h:將pattern space中的內容拷貝到hold space中,原來的hold space裡的內容被清除
H:將pattern space中的內容append到hold space\n後
x:交換pattern space和hold space的內容

反序了一個檔案的行(可以直接用tac命令反序)
[root@www ~]# cat c.txt
11111
22222
33333
aaaaa
bbbbb
ccccc
[root@www ~]# sed '1!G;h;$!d' c.txt
ccccc
bbbbb
aaaaa
33333
22222
11111

其中的 ’1!G;h;$!d’ 可拆解為三個命令:
1!G —— 只有第一行不執行G命令,將hold space中的內容append回到pattern space
h —— 第一行都執行h命令,將pattern space中的內容拷貝到hold space中
$!d —— 除了最後一行不執行d命令,其它行都執行d命令,刪除當前行

[root@www ~]# tac c.txt
ccccc
bbbbb
aaaaa
33333
22222
11111

找到以north開頭的行並在其後新增很多wang和huan,\n表示換行
[root@www ~]# cat e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
[root@www ~]# sed '/^north/a\FUCK FUCK FUCK FUCK \nkcuf kcuf kcuf kcuf' e.txt
northwest NW Charles Main 3.0 .98 3 34
FUCK FUCK FUCK FUCK
kcuf kcuf kcuf kcuf
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
FUCK FUCK FUCK FUCK
kcuf kcuf kcuf kcuf
north NO Margot Weber 4.5 .89 5 9
FUCK FUCK FUCK FUCK
kcuf kcuf kcuf kcuf
central CT Ann Stephens 5.7 .94 5 13

--------------------------------------------------------------------------------------------------------
發現在bash中只能像上面那樣輸入且a後的\可有可無 ; 並不像書上說的那樣,不知是不是跟SHELL有關係
一般,a後是要帶\的,有時還要帶兩個。如果要新增的文字不止一行的話,除了最後一行每一行的結尾都要跟\。以上只是在控制檯輸入,在指令碼中輸入的情況還是和書上說的一樣的。
--------------------------------------------------------------------------------------------------------

在以central開頭的行前分行插入FUCK
[root@www ~]# sed '/central/i\F\nU\nC\nK' e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
F
U
C
K
central CT Ann Stephens 5.7 .94 5 13

--------------------------------------------------------------------------------------------------------
一般,如果要新增的文字不止一行的話,除了最後一行每一行的結尾都要跟\。但在我這裡好像有點不一樣,在終端直接輸入時。
--------------------------------------------------------------------------------------------------------

把有sourth的行全部用FUCK取代
[root@www ~]# sed '/south/c\FUCK' e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
FUCK
FUCK
FUCK
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13

用FUCK替換所有以south開頭的行中的south.
[root@www ~]# sed '/^south/s/south/FUCK/g' e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
FUCKwest SW Lewis Dalsass 2.7 .8 2 18
FUCKern SO Suan Chin 5.1 .95 4 15
FUCKeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13

尋找大於1少於10的一位小數並用FUCK+&替代。這裡的&儲存了前面的小數
[root@www ~]# sed 's/[0-9]\.[0-9]/FUCK&/' e.txt
northwest NW Charles Main FUCK3.0 .98 3 34
western WE Sharon Gray FUCK5.3 .97 5 23
southwest SW Lewis Dalsass FUCK2.7 .8 2 18
southern SO Suan Chin FUCK5.1 .95 4 15
southeast SE Patricia Hemenway FUCK4.0 .7 4 17
eastern EA TB Savage FUCK4.4 .84 5 20
northeast NE AM Main Jr. FUCK5.1 .94 3 13
north NO Margot Weber FUCK4.5 .89 5 9
central CT Ann Stephens FUCK5.7 .94 5 13

p也會把匹配的行列印兩次。也就是說不使用-n選項的話,p會列印出匹配兩次
[root@www ~]# sed '/north/p' e.txt
northwest NW Charles Main 3.0 .98 3 34
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13

P--多行列印:在執行完所有命令後模式空間的內容會自動輸出,在下面的例子中可以看到匹配的行輸出了兩次,但是-n選項會抑制這個動作。只有在與D,N配合使用時才會輸出模式空間裡的第一行,此時不用-n選項。
[root@www ~]# sed '/north/P' e.txt
northwest NW Charles Main 3.0 .98 3 34
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13

多行刪除:選項看到d與D的不同之處了麼?其中空行分別為1,2,3,4行。
[root@www ~]# cat g.txt
this is a test line

this is a test line


this is a test line

 

this is a test line

 


this ia a test line
[root@www ~]# sed -e '/^$/N' -e '/^\n$/d' g.txt
this is a test line

this is a test line
this is a test line

this is a test line
this ia a test line

[root@www ~]# sed -e '/^$/N' -e '/^\n$/D' g.txt
this is a test line

this is a test line

this is a test line

this is a test line

this ia a test line

--------------------------------------------------------------------------------------------------------
可以看到,與N配合的情況下:
使用d,若有偶數個空行將會全被刪除,若有奇數個空行將會保留一行。這是因為d刪除的是整個模式空間的內容。一旦遇到第一個空行就馬上讀入下一行,然後兩行都刪除。如果第三行為空且下一行不為空則命令不執行,空行被輸出。
使用D,當遇到兩個空行時D會刪除兩個空行中的第一個,然後再讀入下一行,如果是空行則刪除第一行,如果空行後有文字則模式空間可以正常輸出。
--------------------------------------------------------------------------------------------------------

r--從檔案中讀取:從test中讀取相關的內容新增到e.txt中所有匹配的行的後面。
[root@www ~]# cat test
sssss
11111
[root@www ~]# cat e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13

[root@www ~]# sed '/^south/r test' e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
sssss
11111
southern SO Suan Chin 5.1 .95 4 15
sssss
11111
southeast SE Patricia Hemenway 4.0 .7 4 17
sssss
11111
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13

w--寫入檔案:把e.txt中所有匹配的行寫入到test檔案中
[root@www ~]# sed '/^south/w test' e.txt|cat test
sssss
11111
[root@www ~]# cat test
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17

n--next:如果有能匹配western行,則n命令使得sed讀取下一行,然後執行相應命令
[root@www ~]# cat e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13

[root@www ~]# sed -e '/western/n' -e 's/SW/FUCK/' e.txt|head -n 4
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest FUCK Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15

y--變換:
[root@www ~]# sed '3,5y/s/S/' e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
SouthweSt SW LewiS DalSaSS 2.7 .8 2 18
Southern SO Suan Chin 5.1 .95 4 15
SoutheaSt SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13

[root@www ~]# sed '1y/3/9/' e.txt
northwest NW Charles Main 9.0 .98 9 94
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13

--------------------------------------------------------------------------------------------------------
替換的型別要一致,數字與字母之間不能相互替換。
且對正規表示式的元字元不起作用。
--------------------------------------------------------------------------------------------------------

q--退出:
列印三行後退出
[root@www ~]# sed '3q' e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18

用相應的字元做出替換後退出
[root@www ~]# sed -e 'y/northwest/ABCDEFGHI/' -e q e.txt
ABCDEFGHD NW CEaClGH MaiA 3.0 .98 3 34

或者
[root@www ~]# sed '{ y/northwest/ABCDEFGHI/; q;}' e.txt
ABCDEFGHD NW CEaClGH MaiA 3.0 .98 3 34

多個命令寫在一行時可以用-e選項,也可以用花括號把所有命令括起來並用分號隔開且最後一個分號可有可無。

H/h/G/g--儲存和取得
[root@www ~]# sed -e '/northeast/h' -e '$g' e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
northeast NE AM Main Jr. 5.1 .94 3 13

[root@www ~]# sed -e '/northeast/h' -e '$G' e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
northeast NE AM Main Jr. 5.1 .94 3 13
[root@www ~]# sed -e '/northeast/H' -e '$g' e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9

northeast NE AM Main Jr. 5.1 .94 3 13
[root@www ~]# sed -e '/northeast/H' -e '$G' e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13

northeast NE AM Main Jr. 5.1 .94 3 13

H/G在相應空間的內容之後放置一個換行符,且後面緊跟模式空間的內容;而g/h的呢都是取代相應空間的內容,所以就有上面的不同結果。

x--交換模式/保持空間內容
首先匹配第一個包含north的行放入保持快取,然後匹配第一個包含south的行放入模式空間,最後把兩者的內容交換。
[root@www ~]# sed -e '/north/h' -e '/south/x' e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
northwest NW Charles Main 3.0 .98 3 34
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13

--------------------------------sed指令碼用法----------------------------------
[root@www ~]# cat e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13

[root@www ~]# cat sedscripts
/central/a\
------This is a test--------
/northeast/i\
------This is a test too------

[root@www ~]# sed -f sedscripts e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
------This is a test too------
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
------This is a test--------

可以在裡面新增註釋,以#開頭的行被認為是註釋
如有多行,則每行都要以\結尾,除了最後一行。
如下面的指令碼是可以正常執行的。
[root@www ~]# cat sedscripts
#This script is a test for sed commands list

/central/a\
------This is a test too--------\
------Hi am here----------------\

#now ,the second test
/northeast/i\
------This is a test ------

[root@www ~]# sed -f sedscripts e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
------This is a test ------
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
------This is a test too--------
------Hi am here----------------

--------------------------------高階流控制命令--------------------------------
b 分支 :無條件轉移
t 測試 :有條件的轉移
它們將指令碼中的控制轉移到包含特殊標籤的行;如果沒有標籤則直接轉移到指令碼的末尾。只有當替換命令改變當前行時才會被執行。

標籤:任意的字元組合且長度不大於7,它本身佔據一行且以冒號開頭
:mylabel
冒號和標籤之間不能有空格,標籤後的空格會被當做標籤的一部分。
標籤和命令之間允許有空格。

b 分支:[address] b [label]
b --> branch,在指令碼中將控制權轉到另一行,通過它你可以跳到你想去的地方,是不是有點像c中的goto呀?
它可以將一組命令當做一個過程來執行且這個過程在指令碼中可以重複執行,只要條件滿足。

b--分支
匹配以north加空格開頭的行,若匹配則轉到:label後面的命令,在以s開頭的行前插入FFFFFFFFFFFFFFUCK ;
[root@wutao ~]# cat sedscripts
#This script is a test for sed commands
:label
/^s/i\
FFFFFFFFFFFFFFUCK
/^north / b label

[root@wutao ~]# sed -f sedscripts e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
FFFFFFFFFFFFFFUCK
southwest SW Lewis Dalsass 2.7 .8 2 18
FFFFFFFFFFFFFFUCK
southern SO Suan Chin 5.1 .95 4 15
FFFFFFFFFFFFFFUCK
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13

其實這也是個迴圈,反覆執行兩個標籤間的命令,直到模式不匹配。但是,如上,不管匹配與否兩個標籤間的內容至少會被執行一次。
也就是說,正常情況下上面的命令都會被執行一次。看下面的例子:
[root@wutao ~]# cat sedscripts
#This script is a test for sed commands
:label
/^n/d
/^A/b label
/^cent/a\
--FUCK!!! \
Just a test! \
Take it easy!!!

[root@wutao ~]# sed -f sedscripts e.txt
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
central CT Ann Stephens 5.7 .94 5 13
--FUCK!!!
Just a test!
Take it easy!!!

看到了吧!雖然模式不匹配,但還是執行了兩個標籤間的內容,嘿嘿!再看看上面,和do-while語句有什麼異同?

如果匹配,什麼都不做,否則執行後的命令向以cent開頭的行後新增一些內容
[root@wutao ~]# cat sedscripts
#This script is a test for sed commands
:label
/^A/b label
/^cent/a\
--FUCK!!! \
Just a test! \
Take it easy!!!

[root@wutao ~]# sed -f sedscripts e.txt
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
--FUCK!!!
Just a test!
Take it easy!!!

另一種迴圈模式
command1
/pattern/b label
command2
label:
command3
首先執行command1,然後看模式是否匹配,若匹配則執行command3,否則執行command2,command3
[root@wutao ~]# cat sedscripts
#This script is a test for sed commands
/^n/d
/^A/b label
s/south/SSSSSS/
:label
/^cent/a\
--FUCK!!! \
Just a test! \
Take it easy!!!

[root@wutao ~]# sed -f sedscripts e.txt
western WE Sharon Gray 5.3 .97 5 23
SSSSSSwest SW Lewis Dalsass 2.7 .8 2 18
SSSSSSern SO Suan Chin 5.1 .95 4 15
SSSSSSeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
central CT Ann Stephens 5.7 .94 5 13
--FUCK!!!
Just a test!
Take it easy!!!

模式不匹配,順序執行各命令,下面來看匹配的情況:
[root@wutao ~]# cat sedscripts
#This script is a test for sed commands
/^w/d
#north後有一個空格
/^north /b label
s/south/SSSSSS/
:label
/^cent/a\
--FUCK!!! \
Just a test! \
Take it easy!!!

[root@wutao ~]# sed -f sedscripts e.txt
northwest NW Charles Main 3.0 .98 3 34
SSSSSSwest SW Lewis Dalsass 2.7 .8 2 18
SSSSSSern SO Suan Chin 5.1 .95 4 15
SSSSSSeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
--FUCK!!!
Just a test!
Take it easy!!!

很顯然,這裡並沒有跳過第二個命令,但是理論上只模式空間匹配的話就會直接轉到:label後的命令的呀!這到底是為什麼呢?來看下一個指令碼,只對上個指令碼做一點點修改:
[root@wutao ~]# cat sedscripts
#This script is a test for sed commands
/^w/d
#north後有一個空格
/^north /b label
s/north /SSSSSS/
:label
/^cent/a\
--FUCK!!! \
Just a test! \
Take it easy!!!
[root@wutao ~]# sed -f sedscripts e.txt
northwest NW Charles Main 3.0 .98 3 34
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
--FUCK!!!
Just a test!
Take it easy!!!

這次結果正常啦,它找到了以north加空格開頭的行,並跳過了第二個命令。
再來看兩個例子:
在第二個命令後再新增一個命令s/south/NNNNNN看會有怎樣的結果:
[root@wutao ~]# cat sedscripts
#This script is a test for sed commands
/^w/d
/^north /b label
s/north /SSSSSS/
s/south/NNNNNN/
:label
/^cent/a\
--FUCK!!! \
Just a test! \
Take it easy!!!

[root@wutao ~]# sed -f sedscripts e.txt
northwest NW Charles Main 3.0 .98 3 34
NNNNNNwest SW Lewis Dalsass 2.7 .8 2 18
NNNNNNern SO Suan Chin 5.1 .95 4 15
NNNNNNeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
--FUCK!!!
Just a test!
Take it easy!!!

顯然,s/north /SSSSSS/ 沒有被執行而s/south/NNNNNN/ 被執行啦

又一個例子:
[root@wutao ~]# cat sedscripts
#This script is a test for sed commands
/^w/d
/^north/b label
p
:label
/^cent/a\
--FUCK!!! \
Just a test! \
Take it easy!!!

[root@wutao ~]# sed -f sedscripts e.txt
northwest NW Charles Main 3.0 .98 3 34
southwest SW Lewis Dalsass 2.7 .8 2 18
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
central CT Ann Stephens 5.7 .94 5 13
--FUCK!!!
Just a test!
Take it easy!!!

可以看到p應用到了除以north開頭的所有行!再來一個例子:
[root@wutao ~]# cat sedscripts
#This script is a test for sed commands
/^w/d
/^north/b label
p
l
:label
/^cent/a\
--FUCK!!! \
Just a test! \
Take it easy!!!

[root@wutao ~]# sed -f sedscripts e.txt
northwest NW Charles Main 3.0 .98 3 34
southwest SW Lewis Dalsass 2.7 .8 2 18
southwest SW Lewis Dalsass 2.7 .8 2 18$
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southern SO Suan Chin 5.1 .95 4 15$
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
southeast SE Patricia Hemenway 4.0 .7 4 17$
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
eastern EA TB Savage 4.4 .84 5 20$
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
central CT Ann Stephens 5.7 .94 5 13$
central CT Ann Stephens 5.7 .94 5 13
--FUCK!!!
Just a test!
Take it easy!!!

看到了麼?P,l都只應用到了除以north開頭的所有行上!!!
從上面的一堆例子中,可以得到:在
command1
/pattern/b label
command2
label:
command3
模式中 只有 針對 匹配pattern的行 的操作才會被跳過!

如何指定執行上例中的command2或command3中的一個
commmand1
/pattern/b label
command2
b
:label
command3
首先執行command1,然後執行/pattern/b label,如果模式匹配則直接跳到command3並執行相關命令,否則跳到command2在執行完相關命令後遇到分支b,分支b將控制轉到指令碼的結尾,繞過了command3.
下面看一個簡單的例子:
[root@wutao ~]# cat sedscripts
#This script is a test for sed commands
/^e/d
/^DDD/b label
s/west/SSSSSS/
b
:label
/^cent/a\
--FUCK!!! \
Just a test! \
Take it easy!!!
[root@wutao ~]# sed -f sedscripts e.txt
northSSSSSS NW Charles Main 3.0 .98 3 34
SSSSSSern WE Sharon Gray 5.3 .97 5 23
southSSSSSS SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13

果然當模式不匹配時只執行command2而:label後的命令沒有被執行

t: [address] t [label]
t-->test,如果在當前匹配的行上成功地進行了替換,那麼t命令就轉到標籤處或指令碼末尾(未給定標籤預設指向指令碼末尾)。
t要單獨成行
下面來一個簡單的例子:
[root@wutao ~]# cat sedscripts
/^s/d
/^west/s/west/QQQ/
t label1
/^n/y/nort/FUCK/
t label
:label
/^F/y/FUCK/nort/
:label1
/^QQQ/s/QQQ/west/

[root@wutao ~]# sed -f sedscripts e.txt
northwest NW rharles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13

[root@wutao ~]# cat sedscripts
/^s/d
/^west/y/Q/a/
t label1
/^n/y/nort/FUCK/
t label
:label
/^F/y/FUCK/nort/
:label1
/^n/y/FUCK/nort/

[root@wutao ~]# sed -f sedscripts e.txt
northwest NW rharles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13

相關文章