1. 程式人生 > 實用技巧 >Linux shell 之 sed 命令詳解 第三部分

Linux shell 之 sed 命令詳解 第三部分

Linux shell 之 sed 命令詳解 第三部分

  目錄:

    五、修改行

    六、轉換命令

    七、回顧列印

    八、使用 sed 處理檔案

五、修改行

  修改( change)命令允許修改資料流中整行文字的內容。它跟插入和附加命令的工作機制一樣,你必須在sed命令中單獨指定新行。

1 sed '3c\
2 > This is a changed line of text.' data4.txt
3 This is line number 1
4 This is line number 2
5 This is a changed line of text.
6 This is line number 4 7 This is line number 5 8 $

  在這個例子中,sed 編輯器會修改第三行中的文字。也可以用文字模式來定址。

1 $ sed '/number 3/c\
2 > This is a changed line of text.' data4.txt
3 This is line number 1
4 This is line number 2
5 This is a changed line of text.
6 This is line number 4
7 This is line number 5
8 $

  文字模式修改命令會修改它匹配的資料流中的任意文字行。

 1 $ sed '/number 1/c\
 2 > This is a changed line of text.' data5.txt
 3 This is a changed line of text.
 4 This is line number 2.
 5 This is line number 3.
 6 This is line number 4.
 7 This is line number 5.
 8 This is line number 6.
 9 This is a changed line of text.
10 This is text you want to keep. 11 This is the last line in the file. 12 $

  你可以在修改命令中使用地址區間,但結果未必如願。

 1 $ sed '2,3c\
 2 > This is a new line of text.' data5.txt
 3 This is line number 1.
 4 This is a new line of text.
 5 This is line number 4.
 6 This is line number 5.
 7 This is line number 6.
 8 This is line number 1 again.
 9 This is text you want to keep.
10 This is the last line in the file.
11 $

  sed 編輯器會用這一行文字來替換資料流中的兩行文字,而不是逐一修改這兩行文字。

六、轉換命令

  轉換(transform)命令(y)是唯一可以處理單個字元的 sed 編輯器命令。轉換命令格式如下。

    [address]y/inchars/outchars/

  轉換命令會對 inchars 和 outchars 值進行一對一的對映。inchars 中的第一個字元會被轉換位 outchars 中的第一個字元,第二個字元會被轉換成 outchars 中的第二個字元。這個對映過程會一直持續到處理完指定字元。如果 inchars 和 ouchars 的長度不同,則 sed 編輯器會產生一條錯誤訊息。

 1 $ sed 'y/123/789/' data5.txt
 2 This is line number 7.
 3 This is line number 8.
 4 This is line number 9.
 5 This is line number 4.
 6 This is line number 5.
 7 This is line number 6.
 8 This is line number 7 again.
 9 This is text you want to keep.
10 This is the last line in the file.
11 $

  如你在輸出中看到的,inchars 模式中指定字元的每個例項都會被替換成 outchars 模式中相同位置的那個字元。

  轉換命令是一個全域性命令,也就是說,它會在文字行中找到的所有指定字元自動進行轉換,而不會考慮它們出現的位置。

1 $ echo "This 1 is a test of 1 try." | sed 'y/123/456/'
2 This 4 is a test of 4 try.
3 $

  sed 編輯器轉換了在文字行中匹配到的字元 1 的兩個例項。你無法限定只轉換在特定地方出現的字元。

七、回顧列印

  前面寫過使用 p 標記和替換命令顯示 sed 編輯器修改過的行。另外有 3 個命令也能用來列印資料流中的資訊:

    ⭐ p 命令用來列印文字行;

    ⭐等號( =)命令用來列印行號;

    ⭐l(小寫的L)命令用來列出行。

1、列印行

  跟替換命令中的 p 標記類似, p 命令可以列印 sed 編輯器輸出中的一行。如果只用這個命令,也沒什麼特別的。

1 echo 'this is a test' | sed 'p'
2 this is a test
3 this is a test
4 $

  它所做的就是列印已有的資料文字。列印命令最常見的用法是列印包含匹配文字模式的行。

 1 $ cat data4.txt
 2 This is line number 1
 3 This is line number 2
 4 This is line number 3
 5 This is line number 4
 6 This is line number 5
 7 $
 8 $ sed -n '/number 3/p' data4.txt
 9 This is line number 3
10 $

  在命令列上用-n選項,你可以禁止輸出其他行,只打印包含匹配文字模式的行。

  也可以用它來快速列印資料流中的某些行。

1 $ sed -n '2,3p' data4.txt
2 This is line number 2
3 This is line number 3
4 $

  如果需要在修改之前檢視行,也可以使用列印命令,比如與替換或修改命令一起使用。可以建立一個指令碼在修改行之前顯示該行。

 1 $ sed -n '/3/{
 2 > p
 3 > s/line/tag/p
 4 > }' data4.txt
 5 This is line number 3
 6 This is tag number 3
 7 $
 8 $
 9 $
10 $
11 $ sed -n '3{
12 p
13 s/line/tag/p
14 }' data4.txt
15 This is line number 3
16 This is tag number 3
17 $

  sed 編輯器命令會查詢包含數字3的行,然後執行兩條命令。首先,指令碼用 p 命令來打印出原始行;然後它用 s 命令替換文字,並用 p 標記打印出替換結果。輸出同時顯示了原來的行文字和新的行文字。

2、列印行號

  等號命令會列印行在資料流中的當前行號。行號由資料流中的換行符決定。每次資料流中出現一個換行符, sed 編輯器會認為一行文字結束了。

 1 $ cat data1.txt
 2 the quick brown fox jumps over the lazy dog.
 3 The quick brown fox jumps over the lazy dog.
 4 The quick brown fox jumps over the lazy dog.
 5 The quick brown fox jumps over the lazy dog.
 6 $
 7 zhengchuanyu@zhengchuanyu:~/reverse_xiaoyu$ sed '=' data1.txt
 8 1
 9 the quick brown fox jumps over the lazy dog.
10 2
11 The quick brown fox jumps over the lazy dog.
12 3
13 The quick brown fox jumps over the lazy dog.
14 4
15 The quick brown fox jumps over the lazy dog.
16 $

  sed 編輯器在實際的文字行出現前列印了行號。如果你要在資料流中查詢特定文字模式的話,等號命令用起來非常方便。

1 $ sed -n '/number 4/{
2 > =
3 > p
4 > }' data4.txt
5 4
6 This is line number 4
7 $

  利用 -n 選項,你就能讓 sed 編輯器只顯示包含匹配文字模式的行的行號和文字。

3、列出行

  列出( list)命令( l)可以列印資料流中的文字和不可列印的 ASCII 字元。任何不可列印字元要麼在其八進位制值前加一個反斜線,要麼使用標準C風格的命名法(用於常見的不可列印字元),比如 \t,來代表製表符。

 1 $ cat data4.txt
 2 This is line number 1
 3 This is line number 2
 4 This is line number 3
 5 This is line number 4
 6 This is line number 5
 7 $
 8 $ sed -n 'l' data4.txt
 9 This is line number 1$
10 This is line number 2$
11 This is line number 3$
12 This is line number 4$
13 This is line number 5$
14 $

1 $ cat data6.txt
2 I       love    linux   shell
3 $
4 $ sed -n 'l' data6.txt
5 I\tlove\tlinux\tshell$
6 $

  製表符的位置使用 \t 來顯示。行尾的美元符表示換行符。如果資料流包含了轉義字元,列出命令會在必要時候用八進位制碼來顯示。

1 $ cat data10.txt
2 This line contains an escape character.
3 $
4 $ sed -n 'l' data10.txt
5 This line contains an escape character. \a$
6 $

  data10.txt 文字檔案包含了一個轉義控制碼來產生鈴聲。當用 cat 命令來顯示文字檔案時,你看不到轉義控制碼,只能聽到聲音(如果你的音箱開啟的話)。但是,利用列出命令,你就能顯示出所使用的轉義控制碼。

八、使用 sed 處理檔案

  替換命令包含一些可以用於檔案的標記。還有一些 sed 編輯器命令也可以實現同樣的目標,不需要非得替換文字。

1、寫入檔案

  w 命令用來向檔案寫入行。該命令的格式如下:

    [address]w filename

  filename 可以使用相對路徑或絕對路徑,但不管是哪種,執行 sed 編輯器的使用者都必須有檔案的寫許可權。地址可以是 sed 中支援的任意型別的定址方式,例如單個行號、文字模式、行區間或文字模式。

  下面的例子是將資料流中的前兩行列印到一個文字檔案中。

 1 $ sed '1,2w test.txt' data4.txt
 2 This is line number 1
 3 This is line number 2
 4 This is line number 3
 5 This is line number 4
 6 This is line number 5
 7 $
 8 $ cat test.txt
 9 This is line number 1
10 This is line number 2
11 $

  當然,如果你不想讓行顯示到 STDOUT 上,你可以用 sed 命令的 -n 選項。

  如果要根據一些公用的文字值從主檔案中建立一份資料檔案,比如下面的郵件列表中的,那麼 w 命令會非常好用。

 1 $ cat data11.txt
 2 Blum, R Browncoat
 3 McGuiness, A Alliance
 4 Bresnahan, C Browncoat
 5 Harken, C Alliance
 6 $
 7 $ sed -n '/Browncoat/w Browncoats.txt' data11.txt
 8 $
 9 $ cat Browncoats.txt
10 Blum, R Browncoat
11 Bresnahan, C Browncoat
12 $

  sed 編輯器會只將包含文字模式的資料行寫入目標檔案。

2、從檔案讀取資料

  瞭解瞭如何在 sed 命令列上向資料流中插入或附加文字。讀取( read)命令( r)允許你將一個獨立檔案中的資料插入到資料流中。

  讀取命令的格式如下:

    [address]r filename

  filename 引數指定了資料檔案的絕對路徑或相對路徑。你在讀取命令中使用地址區間,只能指定單獨一個行號或文字模式地址。 sed 編輯器會將檔案中的文字插入到指定地址後。

 1 $ cat data7.txt
 2 I love linux shell
 3 $ sed '$r data7.txt' data4.txt
 4 This is line number 1
 5 This is line number 2
 6 This is line number 3
 7 This is line number 4
 8 This is line number 5
 9 I love linux shell
10 $

  sed 編輯器會將資料檔案中的所有文字行都插入到資料流中。同樣的方法在使用文字模式地址時也適用。

1 $ sed '/number 2/r data12.txt' data6.txt
2 This is line number 1.
3 This is line number 2.
4 This is an added line.
5 This is the second added line.
6 This is line number 3.
7 This is line number 4.
8 $

  如果你要在資料流的末尾新增文字,只需用美元符地址符就行了。

  讀取命令的另一個很酷的用法是和刪除命令配合使用:利用另一個檔案中的資料來替換檔案中的佔位文字。舉例來說,假定你有一份套用信件儲存在文字檔案中:

1 $ cat notice.std
2 Would the following people:
3 LIST
4 please report to the ship's captain.
5 $

  套用信件將通用佔位文字 LIST 放在人物名單的位置。要在佔位文字後插入名單,只需讀取命令就行了。但這樣的話,佔位文字仍然會留在輸出中。要刪除佔位文字的話,你可以用刪除命令。結果如下:

 1 $ sed '/LIST/{
 2 > r data11.txt
 3 > d
 4 > }' notice.std
 5 Would the following people:
 6 Blum, R Browncoat
 7 McGuiness, A Alliance
 8 Bresnahan, C Browncoat
 9 Harken, C Alliance
10 please report to the ship's captain.
11 $

  現在佔位文字已經被替換成了資料檔案中的名單。