sed 是一個流編輯器(stream editor),主要用來執(zhí)行文本替換。但 sed 的主要設(shè)計目的是以批處理的方式而不是交互的方式來編輯文件。
命令簡介
基本命令格式
sed [常用選項] 命令文本 輸入
常用選項
-n (--quiet, --silent):安靜模式。在 sed 的基本用法中,所有來自標準輸出的信息都會被列出到終端上。加上 -n 參數(shù)后,則只有被sed 處理的那些行才會被輸出。
-e:指定在指令列模式上執(zhí)行的命令文本。默認不需要指定,只有同時要執(zhí)行多個命令文本時才需要顯式的指定 -e 選項。
-f:同時要執(zhí)行多個命令文本時,可以將這些命令文本寫到一個文件中,然后通過 -f filename 的方式使用。
-r:sed 默認使用基礎(chǔ)正則表達式語法(BRE),指定 -r 選項后使用擴展正則表達式語法(ERE)。
-i:直接修改讀取的文檔,而不是輸出到終端。
常用命令
a:新增行, a 的后面接字串,這些字串會被添加到匹配行的下面。
c:替換行, c 的后面接字串,這些字串會替換掉匹配到的行。
d:刪除行,刪除匹配到的行。
i:插入行, i 的后面接字串,這些字串會被插入到匹配行的上面。
p:打印,將某些行輸出。通常 p 會與參數(shù) -n 一起使用,這樣只輸出匹配到的行。
s:字符串替換,主要搭配正則表達式使用。
解釋一下本文中 "命令" 與 "命令文本" 的區(qū)別:
命令是一些抽象的操作,比如 a 指示新增行,d 指示刪除行。
命令文本則是由命令和其它一些信息組合起來的一個字符串,用來執(zhí)行具體的操作。
比如在第一行下面添加一行,內(nèi)容為 'Hello world',命令文本為:'1a Hello world'
再如刪除包含字符串 'Hello world' 的行,命令文本為:'/Hello world/d'
常用選項及命令詳解
說明:本文示例中 demo 文件 test.txt 包含三行文字,內(nèi)容為:
aa bb cc
demo 文件 hello.txt 包含三行文字,內(nèi)容為:
Hello world! Hello Jack! Hello China! Hello Nick!
刪除行
刪除行需要使用命令 d:
$ sed '1d' test.txt # 刪除第一行 $ sed '$d' test.txt # 刪除最后一行 $ sed '1,2d' test.txt # 刪除第一行到第二行 $ sed '2,$d' test.txt # 刪除第二行到最后一行
注意,執(zhí)行完上面的命令,我們只能在命令行終端上看到正確的結(jié)果,而 test.txt 文件根本沒有發(fā)生變化:
選項 -i
如果想要直接在原文件上進行修改(其實是先修改文件的內(nèi)容,然后保存到原文件中),需要使用選項 -i:
$ sed -i '1d' test.txt
注意,應(yīng)用 -i 選項后命令行上沒有輸出內(nèi)容,但是源文件被更新了。
新增行
a 命令可以在匹配的行下面新增行:
$ sed '1a Hello world!' test.txt # 在第一行下面新增一行,內(nèi)容為 "Hello world!"$ sed '$a Hello world!' test.txt # 在最后一行下面新增一行,內(nèi)容為 "Hello world!"$ sed '1,3a Hello world!' test.txt # 在第一行,第二行和第三行下面分別增加一行,內(nèi)容 # 為 "Hello world!" 1,3 表示從第一行到第三行 $ sed '1a Hello world!\nHello China!' test.txt # 一次增加多行需要使用換行符 \n
選項 -e
-e 選項用來指定命令文本,如果只有一個命令文本時 -e 選項可以省略。如何要指定多個命令文本就需要使用 -e 選項。
$ sed -e '1a xxx' -e '2a yyy' test.txt
插入行
i 命令可以在匹配的行上面插入行,語法與新增行相同,只是新行在指定行的上面(與 a 命令的區(qū)別):
選項 -f
前面我們通過選項 -e 添加了多個命令文本,但是如果需要添加比較多的命令文本,使用選項 -e 就不太合適了。因為把所有的命令文本全部寫在命令行中會導(dǎo)致維護困難。此時選項 -f 就派上用場了。我們可以把多個命令文本寫入到文本文件中,然后通過 -f 選項進行引用。
我們創(chuàng)建一個叫 commands 的文件,在里面添加三個命令文本如下:
1i Hello world! 2i Hello world! 3i Hello world!
然后執(zhí)行命令:
$ sed -f commands test.txt
通過 -f 選項,commands 文件中的三個命令文本都被執(zhí)行了!
替換行
使用 c 命令可以輕松的進行整行替換:
$ sed '1c Hello world!' test.txt # 把第一行替換為 "Hello world!"$ sed '1,3c Hello world!' test.txt # 把第一行到第三行替換為 "Hello world!"
注意,上圖中的命令把三行文本替換成了一行文本!
字符串替換
與行替換不同,s 命令只替換匹配到的內(nèi)容(一般為字符串):
$ sed 's/Hello/Hi/' hello.txt # 把Hello 替換為 Hi
上圖帶給我們的困惑之一是:為什么第一行中只有第一個 Hello 被替換了?答案是 sed 默認只會替換第一個匹配到的內(nèi)容!那么我們的第二個困惑來了:如果只替換第一個匹配到的內(nèi)容,那么為什么第二行和第三行的 Hello 都被替換了呢?這個問題涉及的 sed 的工作方式,sed 是一個以行為單位進行文本處理的工具!所以圖中的三行是被分為三次,每次一行進行處理的。因而第二行和第三行中的 Hello 對于本行來說都是第一個匹配到的內(nèi)容,被替換是正確的。
要進行全局替換,需要在命令文本中指定 g,試試下面的命令:
$ sed 's/Hello/Hi/g' hello.txt # 把匹配到的所有Hello 都替換為 Hi
這下第一行中的兩個 Hello 都被替換了。
我們還可以限制執(zhí)行替換操作的行:
$ sed '2,3s/Hello/Hi/g' hello.txt # 只在第二行和第三行進行替換操作
當(dāng)然也可以通過替換來刪除不需要的字符串:
$ sed 's/Hello//g' hello.txt # 刪除字符串 Hello
定界符
雖然 / 是最常用的定界符,但是你也可以使用其它的字符。舉個簡單的例子,當(dāng)你要在 linux 下進行路徑替換時,使用 / 作為定界符是很不爽的(需要很多的轉(zhuǎn)義符),此時換一個定界符是最好的解決方案:
上圖中我們使用分號作為定界符輕松實現(xiàn)了路徑替換。
匹配
細心的同學(xué)可能已經(jīng)注意到了,sed 所有的操作都是建立在行定位之上的。也就是說無論你要干什么,都要先找到(匹配)目標行。連最簡單的刪除行 '1d',也得先定位到第一行,然后才能刪除。所以唯一能限制我們發(fā)揮 sed 能力的因素就是:如何匹配到期望的行?
答案是掌握基本的規(guī)則,然后多練習(xí)! -n 選項和 p 命令是我們練習(xí)的好幫手。-n 選項告訴 sed 只輸出那些被處理過的行。比如 sed '1a Hello world!' test.txt 命令默認會輸出四行,應(yīng)用 -n 后只輸出一行:
p 命令則告訴 sed 只輸出那些匹配到的行, 比如命令:
$ sed -n '1p' test.txt 和命令sed -n '2,3s/Hello/Hi/gp' hello.txt
行匹配的規(guī)則大概有兩類:通過行號進行匹配和通過正則表達式進行匹配。
下面是一些通過行號進行匹配的例子:
$ sed -n '1p' test.txt # 匹配第一行 $ sed -n '$p' test.txt # 匹配最后一行 $ sed -n '2,3p' test.txt # 匹配第二行和第三行 $ sed -n '3,$p' test.txt # 匹配第三行和第三行后的每一行
下面是通過正則表達式進行匹配的例子:
$ sed -n '/Hello/p' hello.txt
默認的匹配是區(qū)分大小寫的,要忽略大小寫可以使用I(大寫字母i)
$ sed -n '/hello/Ip' hello.txt
下面幾個是正則表達式匹配后執(zhí)行操作的例子:
$ sed '/Hello/d' hello.txt # 找到匹配的行,并刪除 $ sed '/Hello/a world!' hello.txt # 找到匹配的行,并在它們下面添加新行 $ sed '/Hello/s/world/China/g' hello.txt # 找到匹配的行,在這些行中執(zhí)行替換
總結(jié)
sed 是一個強有力的文本替換工具,尤其是需要在自動化的場景中使用的時候。本文結(jié)合實例比較詳細的介紹了 sed 的使用方法,希望對大家了解、使用 sed 有所幫助。
作者:sparkdev
出處:http://www.cnblogs.com/sparkdev/
本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。
http://www.cnblogs.com/sparkdev/p/7138073.html