在很多 shell 腳本的工作都從通過(guò) grep 或 egrep 去除所需的文本開(kāi)始。 正則表達(dá)式查找的最初結(jié)果,往往就成了要拿來(lái)作進(jìn)一步處理的” 原始數(shù)據(jù)”。 通常,文本替換至少需要做一件事,就是講一些字以另一些字取代,或者刪除匹配行的某個(gè)部分。執(zhí)行文本替換的正確程序應(yīng)該是 sed----流編輯器。
sed 的設(shè)計(jì)就是用來(lái)批處理而不是交互的方式編輯文件。 當(dāng)藥做好幾個(gè)變化的時(shí)候,不管是對(duì)一個(gè)還是對(duì)數(shù)個(gè)文件,比較簡(jiǎn)單的方式就是將這些變更部分寫(xiě)到一個(gè)編輯的腳本里,再將此腳本應(yīng)用到所有必須修改的文件,sed 的存在目的就在這里。
在 shell 里,sed 主要用于一些簡(jiǎn)單的文本替換,所以我們先從他開(kāi)始。
基本用法:
我們經(jīng)常在管道中間使用 sed,用來(lái)執(zhí)行替換操作,做法是使用 s 命令 ---- 要求正則表達(dá)式尋找,用替換文本替換匹配的文本呢,以及可選的標(biāo)志:
sed ‘s’:.*//’ /etcpasswd |
刪除第一個(gè)冒號(hào)之后所有的東西sort -u
排序列表并刪除重復(fù)部分sed 的語(yǔ)法:
sed [-n] ‘editing command’ [file...]
sed [-n] -e ‘editing command’ [file...]
sed [-n] -f script-file... [file...]
用途:
sed 可刪除 (delete)、改變 (change)、添加 (append)、插入 (insert)、合、交換文件中的資料行,或讀入其它檔的資料到文 > 件中,也可替換 (substuite) 它們其中的字串、或轉(zhuǎn)換 (tranfer) 其中的字母等等。例如將文件中的連續(xù)空白行刪成一行、"local" 字串替換成 "remote"、"t" 字母轉(zhuǎn)換成 "T"、將第 10 行資料與第 11 資料合等。
總合上述所言,當(dāng) sed 由標(biāo)準(zhǔn)輸入讀入一行資料并放入 pattern space
時(shí),sed 依照 sed script
的編輯指令逐一對(duì) pattern space
內(nèi)的資料執(zhí)行編輯,之後,再由 pattern space
內(nèi)的結(jié)果送到標(biāo)準(zhǔn)輸出,接著再將下一行資料讀入。 如此重執(zhí)行上述動(dòng)作,直至讀完所有資料行為止。
記住:
主要參數(shù):
sed -e 'command' file(s)
sed -f scriptfile file(s)
pattern space
。行為模式:
讀取輸入文件的每一行。 假如沒(méi)有文件的話(huà),則是標(biāo)準(zhǔn)輸入。 以每一行來(lái)說(shuō),sed 會(huì)執(zhí)行每一個(gè)應(yīng)用倒數(shù)入行的 esiting command
。 結(jié)果會(huì)寫(xiě)到標(biāo)準(zhǔn)輸出 (默認(rèn)情況下,或是顯式的使用 p 命令及 -n 選項(xiàng))。 若無(wú) -e 或 -f 選項(xiàng),則 sed 會(huì)把第一個(gè)參數(shù)看做是要使用的 editing command
。
find /home/tolstoy -type -d -print
// 尋找所有目錄sed ‘s;/home/tolstor;/home/lt/;’
// 修改名稱(chēng); 注意: 這里使用分號(hào)作為定界符sed ‘s/^/mkdir /’
// 插入 mkdir 命令sh -x
// 以 shell 跟蹤模式執(zhí)行上述腳本是說(shuō)將 /home/tolstoy
目錄結(jié)構(gòu)建立一份副本在 /home.lt
下 (可能是為備份) 而做的準(zhǔn)備
替換案例:
Sed 可替換文件中的字串、資料行、甚至資料區(qū)。其中,表示替換字串的指令中的函數(shù)參數(shù)為 s; 表示替換資料行、或資料區(qū) > 的指令中的函數(shù)參數(shù)為 c。上述情況以下面三個(gè)例子說(shuō)明。
* 行的替換
sed -e '1c/#!/bin/more' file (把第一行替換成#!/bin/more)
思考: 把第 n 行替換成 just do it
sed -e 'nc/just do it' file
sed -e '1,10c/I can do it' file (把 1 到 10 行替換成一行:I can do it)
思考: 換成兩行 (I can do it! Let's start)
sed -e '1,10c/I can do it!/nLet'"/'"'s start' file
* 字符的替換
$ sed 's/test/mytest/g' example
----- 在整行范圍內(nèi)把 test 替換為 mytest。如果沒(méi)有 g 標(biāo)記,則只有每行第一個(gè)匹配的 test 被替換成 mytest。$ sed -n 's/^test/mytest/p' example
-----(-n) 選項(xiàng)和 p 標(biāo)志一起使用表示只打印那些發(fā)生替換的行。也就是說(shuō),如果某一行開(kāi)頭的 test 被替換成 mytest,就打印它。$ sed 's/^192.168.0.1/&localhost/' example
-----& 符號(hào)表示替換換字符串中被找到的部份。所有以 192.168.0.1 開(kāi)頭的行都會(huì)被替換成它自已加 localhost,變成 192.168.0.1localhost。$ sed -n 's/loveable/\1rs/p' example-----love
被標(biāo)記為 1,所有 loveable 會(huì)被替換成 lovers,而且替換的行會(huì)被打印出來(lái)。$ sed 's#10#100#g' example
----- 不論什么字符,緊跟著 s 命令的都被認(rèn)為是新的分隔符,所以,“#” 在這里是分隔符,代替了默認(rèn)的 “/” 分隔符。表示把所有 10 替換成 100。替換與查找
在 s 命令里以 g 結(jié)尾表示的是: 全局性,意即” 替代文本取代正則表達(dá)式中每一個(gè)匹配的”。 如果沒(méi)有設(shè)置 gsed 指揮取代第一個(gè)匹配的。
鮮為人知的是: 可以在結(jié)尾指定數(shù)字,只是第 n 個(gè)匹配出現(xiàn)才要被取代:
sed ‘s/Tom/Lisy/2’ < Test.txt
僅匹配第二個(gè) Tom
通過(guò)給 sed 增加一個(gè) -e 選項(xiàng)的方式能讓 sed 接受多個(gè)命令。sed -e ‘s/foo/bar/g’ -e ‘s/chicken/cow/g’ myfile.txt 1>myfile2.txt
用 shell 命令將 test.log 文件中第 3-5 行的第 2 個(gè)“filter” 替換成“haha”sed -i '3,5s/filter/haha/2' test.log