命令簡介
基本命令格式
sed [常用選項] 命令文本 輸入
常用選項
-n (--quiet, --silent):安靜模式。在 sed 的基本用法中,所有來自標準輸出的信息都會被列出到終端上。加上 -n 參數後,則只有被sed 處理的那些行纔會被輸出。
-e:指定在指令列模式上執行的命令文本。默認不需要指定,只有同時要執行多個命令文本時才需要顯式的指定 -e 選項。
-f:同時要執行多個命令文本時,可以將這些命令文本寫到一個文件中,然後通過 -f filename 的方式使用。
-r:sed 默認使用基礎正則表達式語法(BRE),指定 -r 選項後使用擴展正則表達式語法(ERE)。
-i:直接修改讀取的文檔,而不是輸出到終端。
常用命令
a:新增行, a 的後面接字串,這些字串會被添加到匹配行的下面。
c:替換行, c 的後面接字串,這些字串會替換掉匹配到的行。
d:刪除行,刪除匹配到的行。
i:插入行, i 的後面接字串,這些字串會被插入到匹配行的上面。
p:打印,將某些行輸出。通常 p 會與參數 -n 一起使用,這樣只輸出匹配到的行。
s:字符串替換,主要搭配正則表達式使用。
解釋一下本文中 "命令" 與 "命令文本" 的區別:
命令是一些抽象的操作,比如 a 指示新增行,d 指示刪除行。
命令文本則是由命令和其它一些信息組合起來的一個字符串,用來執行具體的操作。
比如在第一行下面添加一行,內容爲 'Hello world',命令文本爲:'1a Hello world'
再如刪除包含字符串 'Hello world' 的行,命令文本爲:'/Hello world/d'
常用選項及命令詳解
說明:本文示例中 demo 文件 test.txt 包含三行文字,內容爲:
aa bb cc
demo 文件 hello.txt 包含三行文字,內容爲:
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 # 刪除第二行到最後一行
注意,執行完上面的命令,我們只能在命令行終端上看到正確的結果,而 test.txt 文件根本沒有發生變化:
選項 -i
如果想要直接在原文件上進行修改(其實是先修改文件的內容,然後保存到原文件中),需要使用選項 -i:
$ sed -i '1d' test.txt
注意,應用 -i 選項後命令行上沒有輸出內容,但是源文件被更新了。
新增行
a 命令可以在匹配的行下面新增行:
$ sed '1a Hello world!' test.txt # 在第一行下面新增一行,內容爲 "Hello world!"$ sed '$a Hello world!' test.txt # 在最後一行下面新增一行,內容爲 "Hello world!"$ sed '1,3a Hello world!' test.txt # 在第一行,第二行和第三行下面分別增加一行,內容 # 爲 "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 命令的區別):
選項 -f
前面我們通過選項 -e 添加了多個命令文本,但是如果需要添加比較多的命令文本,使用選項 -e 就不太合適了。因爲把所有的命令文本全部寫在命令行中會導致維護困難。此時選項 -f 就派上用場了。我們可以把多個命令文本寫入到文本文件中,然後通過 -f 選項進行引用。
我們創建一個叫 commands 的文件,在裏面添加三個命令文本如下:
1i Hello world! 2i Hello world! 3i Hello world!
然後執行命令:
$ sed -f commands test.txt
通過 -f 選項,commands 文件中的三個命令文本都被執行了!
替換行
使用 c 命令可以輕鬆的進行整行替換:
$ sed '1c Hello world!' test.txt # 把第一行替換爲 "Hello world!"$ sed '1,3c Hello world!' test.txt # 把第一行到第三行替換爲 "Hello world!"
注意,上圖中的命令把三行文本替換成了一行文本!
字符串替換
與行替換不同,s 命令只替換匹配到的內容(一般爲字符串):
$ sed 's/Hello/Hi/' hello.txt # 把Hello 替換爲 Hi
上圖帶給我們的困惑之一是:爲什麼第一行中只有第一個 Hello 被替換了?答案是 sed 默認只會替換第一個匹配到的內容!那麼我們的第二個困惑來了:如果只替換第一個匹配到的內容,那麼爲什麼第二行和第三行的 Hello 都被替換了呢?這個問題涉及的 sed 的工作方式,sed 是一個以行爲單位進行文本處理的工具!所以圖中的三行是被分爲三次,每次一行進行處理的。因而第二行和第三行中的 Hello 對於本行來說都是第一個匹配到的內容,被替換是正確的。
要進行全局替換,需要在命令文本中指定 g,試試下面的命令:
$ sed 's/Hello/Hi/g' hello.txt # 把匹配到的所有Hello 都替換爲 Hi
這下第一行中的兩個 Hello 都被替換了。
我們還可以限制執行替換操作的行:
$ sed '2,3s/Hello/Hi/g' hello.txt # 只在第二行和第三行進行替換操作
當然也可以通過替換來刪除不需要的字符串:
$ sed 's/Hello//g' hello.txt # 刪除字符串 Hello
定界符
雖然 / 是最常用的定界符,但是你也可以使用其它的字符。舉個簡單的例子,當你要在 linux 下進行路徑替換時,使用 / 作爲定界符是很不爽的(需要很多的轉義符),此時換一個定界符是最好的解決方案:
上圖中我們使用分號作爲定界符輕鬆實現了路徑替換。
匹配
細心的同學可能已經注意到了,sed 所有的操作都是建立在行定位之上的。也就是說無論你要幹什麼,都要先找到(匹配)目標行。連最簡單的刪除行 '1d',也得先定位到第一行,然後才能刪除。所以唯一能限制我們發揮 sed 能力的因素就是:如何匹配到期望的行?
答案是掌握基本的規則,然後多練習! -n 選項和 p 命令是我們練習的好幫手。-n 選項告訴 sed 只輸出那些被處理過的行。比如 sed '1a Hello world!' test.txt 命令默認會輸出四行,應用 -n 後只輸出一行:
p 命令則告訴 sed 只輸出那些匹配到的行, 比如命令:
$ sed -n '1p' test.txt 和命令sed -n '2,3s/Hello/Hi/gp' hello.txt
行匹配的規則大概有兩類:通過行號進行匹配和通過正則表達式進行匹配。
下面是一些通過行號進行匹配的例子:
$ 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
默認的匹配是區分大小寫的,要忽略大小寫可以使用I(大寫字母i)
$ sed -n '/hello/Ip' hello.txt
下面幾個是正則表達式匹配後執行操作的例子:
$ sed '/Hello/d' hello.txt # 找到匹配的行,並刪除 $ sed '/Hello/a world!' hello.txt # 找到匹配的行,並在它們下面添加新行 $ sed '/Hello/s/world/China/g' hello.txt # 找到匹配的行,在這些行中執行替換