首頁 > linux教程 > Linux文本處理(Linux三劍客) 閱讀:0更新時間:2020-03-28 00:57:10

Linux sed命令完全攻略(超級詳細)

我們知道,Vim 采用的是交互式文本編輯模式,你可以用鍵盤命令來交互性地插入、刪除或替換數據中的文本。但本節要講的 sed 命令不同,它采用的是流編輯模式,最明顯的特點是,在 sed 處理數據之前,需要預先提供一組規則,sed 會按照此規則來編輯數據。

sed 會根據腳本命令來處理文本文件中的數據,這些命令要么從命令行中輸入,要么存儲在一個文本文件中,此命令執行數據的順序如下:
  1. 每次僅讀取一行內容;
  2. 根據提供的規則命令匹配并修改數據。注意,sed 默認不會直接修改源文件數據,而是會將數據復制到緩沖區中,修改也僅限于緩沖區中的數據;
  3. 將執行結果輸出。
當一行數據匹配完成后,它會繼續讀取下一行數據,并重復這個過程,直到將文件中所有數據處理完畢。

sed 命令的基本格式如下:

[root@localhost ~]# sed [選項] [腳本命令] 文件名

該命令常用的選項及含義,如表 1 所示。

表 1 sed 命令常用選項及含義
選項 含義
-e 腳本命令 該選項會將其后跟的腳本命令添加到已有的命令中。
-f 腳本命令文件 該選項會將其后文件中的腳本命令添加到已有的命令中。
-n 默認情況下,sed 會在所有的腳本指定執行完畢后,會自動輸出處理后的內容,而該選項會屏蔽啟動輸出,需使用 print 命令來完成輸出。
-i 此選項會直接修改源文件,要慎用。

成功使用 sed 命令的關鍵在于掌握各式各樣的腳本命令及格式,它能幫你定制編輯文件的規則。

sed腳本命令

sed s 替換腳本命令

此命令的基本格式為:

[address]s/pattern/replacement/flags

其中,address 表示指定要操作的具體行,pattern 指的是需要替換的內容,replacement 指的是要替換的新內容。

關于指定具體操作行(address)的用法,這里先不做解釋,文章后續會對其做詳細介紹。

此命令中常用的 flags 標記如表 2 所示。

表 2 sed s命令flags標記及功能
flags 標記 功能
n 1~512 之間的數字,表示指定要替換的字符串出現第幾次時才進行替換,例如,一行中有 3 個 A,但用戶只想替換第二個 A,這是就用到這個標記;
g 對數據中所有匹配到的內容進行替換,如果沒有 g,則只會在第一次匹配成功時做替換操作。例如,一行數據中有 3 個 A,則只會替換第一個 A;
p 會打印與替換命令中指定的模式匹配的行。此標記通常與 -n 選項一起使用。
w file 將緩沖區中的內容寫到指定的 file 文件中;
& 用正則表達式匹配的內容進行替換;
\n 匹配第 n 個子串,該子串之前在 pattern 中用 \(\) 指定。
\ 轉義(轉義替換部分包含:&、\ 等)。

比如,可以指定 sed 用新文本替換第幾處模式匹配的地方:

[root@localhost ~]# sed 's/test/trial/2' data4.txt
This is a test of the trial script.
This is the second test of the trial script.

可以看到,使用數字 2 作為標記的結果就是,sed 編輯器只替換每行中第 2 次出現的匹配模式。

如果要用新文件替換所有匹配的字符串,可以使用 g 標記:

[root@localhost ~]# sed 's/test/trial/g' data4.txt
This is a trial of the trial script.
This is the second trial of the trial script.


我們知道,-n 選項會禁止 sed 輸出,但 p 標記會輸出修改過的行,將二者匹配使用的效果就是只輸出被替換命令修改過的行,例如:

[root@localhost ~]# cat data5.txt
This is a test line.
This is a different line.
[root@localhost ~]# sed -n 's/test/trial/p' data5.txt
This is a trial line.


w 標記會將匹配后的結果保存到指定文件中,比如:

[root@localhost ~]# sed 's/test/trial/w test.txt' data5.txt
This is a trial line.
This is a different line.
[root@localhost ~]#cat test.txt
This is a trial line.


在使用 s 腳本命令時,替換類似文件路徑的字符串會比較麻煩,需要將路徑中的正斜線進行轉義,例如:

[root@localhost ~]# sed 's/\/bin\/bash/\/bin\/csh/' /etc/passwd

sed d 替換腳本命令

此命令的基本格式為:

[address]d

如果需要刪除文本中的特定行,可以用 d 腳本命令,它會刪除指定行中的所有內容。但使用該命令時要特別小心,如果你忘記指定具體行的話,文件中的所有內容都會被刪除,舉個例子:

[root@localhost ~]# cat data1.txt
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
[root@localhost ~]# sed 'd' data1.txt
#什么也不輸出,證明成了空文件

當和指定地址一起使用時,刪除命令顯然能發揮出大的功用??梢詮臄祿髦袆h除特定的文本行。

address 的具體寫法后續會做詳細介紹,這里只給大家舉幾個簡單的例子:
  • 通過行號指定,比如刪除 data6.txt 文件內容中的第 3 行:

    [root@localhost ~]# cat data6.txt
    This is line number 1.
    This is line number 2.
    This is line number 3.
    This is line number 4.
    [root@localhost ~]# sed '3d' data6.txt
    This is line number 1.
    This is line number 2.
    This is line number 4.

  • 或者通過特定行區間指定,比如刪除 data6.txt 文件內容中的第 2、3行:

    [root@localhost ~]# sed '2,3d' data6.txt
    This is line number 1.
    This is line number 4.

  • 也可以使用兩個文本模式來刪除某個區間內的行,但這么做時要小心,你指定的第一個模式會“打開”行刪除功能,第二個模式會“關閉”行刪除功能,因此,sed 會刪除兩個指定行之間的所有行(包括指定的行),例如:

    [root@localhost ~]#sed '/1/,/3/d' data6.txt
    #刪除第 1~3 行的文本數據
    This is line number 4.

  • 或者通過特殊的文件結尾字符,比如刪除 data6.txt 文件內容中第 3 行開始的所有的內容:

    [root@localhost ~]# sed '3,$d' data6.txt
    This is line number 1.
    This is line number 2.

在此強調,在默認情況下 sed 并不會修改原始文件,這里被刪除的行只是從 sed 的輸出中消失了,原始文件沒做任何改變。

sed a 和 i 腳本命令

a 命令表示在指定行的后面附加一行,i 命令表示在指定行的前面插入一行,這里之所以要同時介紹這 2 個腳本命令,因為它們的基本格式完全相同,如下所示:

[address]a(或 i)\新文本內容

下面分別就這 2 個命令,給讀者舉幾個例子。比如說,將一個新行插入到數據流第三行前,執行命令如下:

[root@localhost ~]# sed '3i\
> This is an inserted line.' data6.txt
This is line number 1.
This is line number 2.
This is an inserted line.
This is line number 3.
This is line number 4.

再比如說,將一個新行附加到數據流中第三行后,執行命令如下:

[root@localhost ~]# sed '3a\
> This is an appended line.' data6.txt
This is line number 1.
This is line number 2.
This is line number 3.
This is an appended line.
This is line number 4.

如果你想將一個多行數據添加到數據流中,只需對要插入或附加的文本中的每一行末尾(除最后一行)添加反斜線即可,例如:

[root@localhost ~]# sed '1i\
> This is one line of new text.\
> This is another line of new text.' data6.txt
This is one line of new text.
This is another line of new text.
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.

可以看到,指定的兩行都會被添加到數據流中。

sed c 替換腳本命令

c 命令表示將指定行中的所有內容,替換成該選項后面的字符串。該命令的基本格式為:

[address]c\用于替換的新文本

舉個例子:

[root@localhost ~]# sed '3c\
> This is a changed line of text.' data6.txt
This is line number 1.
This is line number 2.
This is a changed line of text.
This is line number 4.
在這個例子中,sed 編輯器會修改第三行中的文本,其實,下面的寫法也可以實現此目的:
[root@localhost ~]# sed '/number 3/c\
> This is a changed line of text.' data6.txt
This is line number 1.
This is line number 2.
This is a changed line of text.
This is line number 4.

sed y 轉換腳本命令

y 轉換命令是唯一可以處理單個字符的 sed 腳本命令,其基本格式如下:

[address]y/inchars/outchars/

轉換命令會對 inchars 和 outchars 值進行一對一的映射,即 inchars 中的第一個字符會被轉換為 outchars 中的第一個字符,第二個字符會被轉換成 outchars 中的第二個字符...這個映射過程會一直持續到處理完指定字符。如果 inchars 和 outchars 的長度不同,則 sed 會產生一條錯誤消息。

舉個簡單例子:

[root@localhost ~]# sed 'y/123/789/' data8.txt
This is line number 7.
This is line number 8.
This is line number 9.
This is line number 4.
This is line number 7 again.
This is yet another line.
This is the last line in the file.

可以看到,inchars 模式中指定字符的每個實例都會被替換成 outchars 模式中相同位置的那個字符。

轉換命令是一個全局命令,也就是說,它會文本行中找到的所有指定字符自動進行轉換,而不會考慮它們出現的位置,再打個比方:

[root@localhost ~]# echo "This 1 is a test of 1 try." | sed 'y/123/456/'
This 4 is a test of 4 try.

sed 轉換了在文本行中匹配到的字符 1 的兩個實例,我們無法限定只轉換在特定地方出現的字符。

sed p 打印腳本命令

p 命令表示搜索符號條件的行,并輸出該行的內容,此命令的基本格式為:

[address]p

p 命令常見的用法是打印包含匹配文本模式的行,例如:

[root@localhost ~]# cat data6.txt
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
[root@localhost ~]# sed -n '/number 3/p' data6.txt
This is line number 3.

可以看到,用 -n 選項和 p 命令配合使用,我們可以禁止輸出其他行,只打印包含匹配文本模式的行。

如果需要在修改之前查看行,也可以使用打印命令,比如與替換或修改命令一起使用??梢詣摻ㄒ粋€腳本在修改行之前顯示該行,如下所示:

[root@localhost ~]# sed -n '/3/{
> p
> s/line/test/p
> }' data6.txt
This is line number 3.
This is test number 3.

sed 命令會查找包含數字 3 的行,然后執行兩條命令。首先,腳本用 p 命令來打印出原始行;然后它用 s 命令替換文本,并用 p 標記打印出替換結果。輸出同時顯示了原來的行文本和新的行文本。

sed w 腳本命令

w 命令用來將文本中指定行的內容寫入文件中,此命令的基本格式如下:

[address]w filename

這里的 filename 表示文件名,可以使用相對路徑或絕對路徑,但不管是哪種,運行 sed 命令的用戶都必須有文件的寫權限。

下面的例子是將數據流中的前兩行打印到一個文本文件中:

[root@localhost ~]# sed '1,2w test.txt' data6.txt
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
[root@localhost ~]# cat test.txt
This is line number 1.
This is line number 2.

當然,如果不想讓行直接輸出,可以用 -n 選項,再舉個例子:

[root@localhost ~]# cat data11.txt
Blum, R       Browncoat
McGuiness, A  Alliance
Bresnahan, C  Browncoat
Harken, C     Alliance
[root@localhost ~]# sed -n '/Browncoat/w Browncoats.txt' data11.txt
cat Browncoats.txt
Blum, R       Browncoat
Bresnahan, C  Browncoat

可以看到,通過使用 w 腳本命令,sed 可以實現將包含文本模式的數據行寫入目標文件。

sed r 腳本命令

r 命令用于將一個獨立文件的數據插入到當前數據流的指定位置,該命令的基本格式為:

[address]r filename

sed 命令會將 filename 文件中的內容插入到 address 指定行的后面,比如說:

[root@localhost ~]# cat data12.txt
This is an added line.
This is the second added line.
[root@localhost ~]# sed '3r data12.txt' data6.txt
This is line number 1.
This is line number 2.
This is line number 3.
This is an added line.
This is the second added line.
This is line number 4.

如果你想將指定文件中的數據插入到數據流的末尾,可以使用 $ 地址符,例如:

[root@localhost ~]# sed '$r data12.txt' data6.txt
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
This is an added line.
This is the second added line.

sed q 退出腳本命令

q 命令的作用是使 sed 命令在第一次匹配任務結束后,退出 sed 程序,不再進行對后續數據的處理。

比如:

[root@localhost ~]# sed '2q' test.txt
This is line number 1.
This is line number 2.

可以看到,sed 命令在打印輸出第 2 行之后,就停止了,是 q 命令造成的,再比如:

[root@localhost ~]# sed '/number 1/{ s/number 1/number 0/;q; }' test.txt
This is line number 0.

使用 q 命令之后,sed 命令會在匹配到 number 1 時,將其替換成 number 0,然后直接退出。

sed 腳本命令的尋址方式

前面在介紹各個腳本命令時,我們一直忽略了對 address 部分的介紹。對各個腳本命令來說,address 用來表明該腳本命令作用到文本中的具體行。

默認情況下,sed 命令會作用于文本數據的所有行。如果只想將命令作用于特定行或某些行,則必須寫明 address 部分,表示的方法有以下 2 種:
  1. 以數字形式指定行區間;
  2. 用文本模式指定具體行區間。

以上兩種形式都可以使用如下這 2 種格式,分別是:

[address]腳本命令

或者

address {
    多個腳本命令
}

以上兩種形式在前面例子中都有具體實例,因此這里不再做過多贅述。

以數字形式指定行區間

當使用數字方式的行尋址時,可以用行在文本流中的行位置來引用。sed 會將文本流中的第一行編號為 1,然后繼續按順序為接下來的行分配行號。

在腳本命令中,指定的地址可以是單個行號,或是用起始行號、逗號以及結尾行號指定的一定區間范圍內的行。這里舉一個 sed 命令作用到指定行號的例子:

[root@localhost ~]#sed '2s/dog/cat/' data1.txt
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog

可以看到,sed 只修改地址指定的第二行的文本。下面的例子中使用了行地址區間:

[root@localhost ~]# sed '2,3s/dog/cat/' data1.txt
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy dog

在此基礎上,如果想將命令作用到文本中從某行開始的所有行,可以用特殊地址——美元符($):

[root@localhost ~]# sed '2,$s/dog/cat/' data1.txt
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy cat

用文本模式指定行區間

sed 允許指定文本模式來過濾出命令要作用的行,格式如下:

/pattern/command

注意,必須用正斜線將要指定的 pattern 封起來,sed 會將該命令作用到包含指定文本模式的行上。

舉個例子,如果你想只修改用戶 demo 的默認 shell,可以使用 sed 命令,執行命令如下:

[root@localhost ~]# grep demo /etc/passwd
demo:x:502:502::/home/Samantha:/bin/bash
[root@localhost ~]# sed '/demo/s/bash/csh/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
...
demo:x:502:502::/home/demo:/bin/csh
...


雖然使用固定文本模式能幫你過濾出特定的值,就跟上面這個用戶名的例子一樣,但其作用難免有限,因此,sed 允許在文本模式使用正則表達式指明作用的具體行。正則表達式允許創建高級文本模式匹配表達式來匹配各種數據。這些表達式結合了一系列通配符、特殊字符以及固定文本字符來生成能夠匹配幾乎任何形式文本的簡練模式。

關于正則表達式,本節不做過多介紹,有興趣的讀者可閱讀《正則表達式入門教程》一文,這里僅給讀者提供一個簡單示例:

[root@localhost ~]# cat test.txt
<html>
<title>First Wed</title>
<body>
h1Helloh1
h2Helloh2
h3Helloh3
</body>
</html>
#使用正則表示式給所有第一個的h1、h2、h3添加<>,給第二個h1、h2、h3添加</>
[root@localhost ~]# cat sed.sh
/h[0-9]/{
    s//\<&\>/1
    s//\<\/&\>/2
}

[root@localhost ~]# sed -f sed.sh test.txt
<h1>Hello</h1>
<h2>Hello</h2>
<h3>Hello</h3>

收到篇幅的限制,本節僅介紹了 sed 命令每次只讀取一行內容并處理,有關 sed 命令如何一次處理多行文本內容,放到下節繼續講解,讀者可點擊《linux sed命令高級用法》繼續學習。

beylze編程學院,一個分享編程知識和seo優化知識的網站。跟著beylze一起學習,每天都有進步。

通俗易懂,深入淺出,一篇文章只講一個知識點。

文章不深奧,不需要鉆研,在公交、在地鐵、在廁所都可以閱讀,隨時隨地漲姿勢。

文章不涉及代碼,不燒腦細胞,人人都可以學習。

當你決定關注beylze(公眾號:beylze),你已然超越了90%的其他從業者!

相關文章

優秀教程

国产亚洲欧美日韩