linux sed 命令

命令簡介

基本命令格式

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  # 找到匹配的行,在這些行中執行替換


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