首頁 > 軟體

sed基本概念及高階命令詳解

2020-06-16 16:52:21

sed基本概念

sed是一款強大的文字處理工具,全程叫stream editor,翻譯過來就是流編輯器。
sed在處理檔案時會依次把檔案每一行讀入緩衝區,稱為模式空間,處理完成後在螢幕顯示並讀入下一行,直到檔案結束或者指定的處理位置結束,處理過程不改變檔案內容,除非使用重定向儲存輸出。其迴圈大致如下:
1、讀取輸入流的一行到模式空間
2、對模式空間中的內容執行script
3、預設輸出並且清空模式空間
4、讀取輸入流的下一行到模式空間
5、對模式空間中的內容執行script
……
其中第一步的讀取我們可以通過客製化來控制sed讀取輸入流的位置,第二步的的script部分是我們操作的重點,注意第三步我們無法干預,即使使用 -n選項也只是輸出空內容並非沒有輸出動作。
其命令格式如下:

sed -[opt] 'script' input_stream

其中script就是sed的命令部分也叫做sed指令碼,是sed內部命令的集合,其格式如下:addr1[,addr2]cmdlist其中例如要對file第2行到第4行進行刪除可以執行sed '2,4d' file其中,2,4用來指定要操作檔案的位置

常用選項

和其他常見命令不同,sed的常用選項很少,這裡挑幾個常用的介紹一下。
-n 預設情況下sed會在匹配處理結束後將模式空間中的內容輸出到螢幕上,使用-n之後會使得sed不在輸出預設空間中的內容而是輸出空內容,注意-n是使預設輸出為空而不是禁用預設輸出動作。

[root@lori bin]$·sed -n '1,3p' file
1
2
3
[root@lori bin]$·sed '1,3p' file
1
1
2
2
3
3

其中p命令用來顯示行,之所以第二個命令中每一行都顯示兩次就是因為在不加-n的情況下sed會預設輸出一次

-e 多點操作,但我的理解更像是sed內部的管道如下:

[root@lori bin]$·echo "what are you doing"| sed -e 's/what/how/' -e 's/how/hello/'
hello are you doing

解釋一下上面的命令,其中s是替換命令,第一個-e 's/what/how/' 把輸入中的what換成了how,然後第二個-e 's/how/hello/' 把第一個結果中的how又換成hello

-i'.bak' 將原始檔重新命名,並儲存臨時檔案,其實現方式是sed在編輯檔案的時候會將檔案的修改寫入到臨時檔案中,然後將原始檔重新命名並且把臨時檔案命名為原始檔名。可以只用 -i 不進行備份,臨時檔案會將原始檔覆蓋,bak部分為自定義內容,可以使用* 代表原始檔名,如sed -i'bak_*' script file 的結果是將原始檔名加bak_字首,並將臨時檔案儲存。

[root@lori test]$·ls -i
1190752 passwd
[root@lori test]$·sed -i.bak '1,3d' passwd
[root@lori test]$·ls -i
1190753 passwd  1190752 passwd.bak

[root@lori test]$·ls -i
1190753 passwd  1190752 passwd.bak
[root@lori test]$·sed -i '1,3d' passwd
[root@lori test]$·ls -i
1190754 passwd  1190752 passwd.bak


上面第一個實驗中,修改後的passwd檔案的inode已經發生變化,而passwd.bak才是原始檔,第二個實驗中,單獨使用-i選項後源passwd已經沒有了,而是生成了一個全新的passwd檔案。

-r 使用擴充套件正則而非基礎正則。

定址表示式

當sed將輸入流中的行讀入到匹配空間之後就開始對讀入的文字進行匹配,符合條件的執行後續命令,不符合條件的直接輸出清空模式空間讀取下一行進行匹配,匹配的過程成為定址,其格式為[addr1][,addr2],總體來說可以分為下面幾種情況。
1、addr1和addr2都不指定的時候表示匹配所有行
2、指定一個地址的時候表示只有能被addr1表示式匹配的行
3、兩個都指定的時候表示從addr1到addr2
其中,無論是addr1還是addr2都支援以下幾種表達方式
N. 直接指定行號,如:sed -n '2,3p' file 顯示file第2行到第3行
/REGEXP/ 正規表示式,如:sed -n '/^root/,/ftp/p' file 顯示第一個匹配到的root開頭的行到第一個包含ftp的行
$ 匹配最後一行(需要注意的是sed在處理完一個檔案之前並不知道檔案有多行,所以類似$-n行的寫法是錯誤的)如:sed -n '$p' file 顯示檔案的最後一行
~符號,步進,例如sed -n '1~3p' file表示從第一行開始每隔三行進行輸出顯示
'ADDR1,+N' 匹配 ADDR1和其後的 N行。
另外在定址表示式後面加上!表示匹配未被表示式匹配到的行。例如:sed -n '3,6!p' file不顯示檔案3到6行

常用命令

不過多的介紹命令,而是通過流程圖嘗試理解sed執行原理

輸出命令p

前面已經見過很多次了,p命令會輸出當前模式空間中的內容,即使使用了-n,嚴格來說-n只是影響了預設輸出,如下:

[root@lbaby ~]# echo -e "abcndef"|sed '2p'
abc
def        p命令輸出
def        預設輸出

d命令

d命令用來清空當前模式空間中的內容,其迴圈和p命令類似,需要注意的是d後面的命令不會執行,因為模式空間中沒有內容。如:

[root@lbaby ~]# echo -e "abcndef"|sed '2d'
abc

q或Q退出命令

q和Q用來立即退出sed程式。不同的是q命令依舊會執行預設輸出,而Q命令直接退出,同時這兩個命令都可以指定程式退出狀態碼:

[root@lbaby ~]# echo -e "abcndef"|sed '1q 3'
abc
[root@lbaby ~]# echo $?
3
[root@lbaby ~]# echo -e "abcndef"|sed '1Q 4'
[root@lbaby ~]# echo $?
4

注意第一條命令中的輸出來自預設輸出並非q命令,驗證這一點很簡單,加上 -n選項就能明白了。其大概流程如下圖:
sed基礎

n 讀取下一行

讀取匹配的行的下一行,讀取之前依舊會輸出模式空間裡的行並且清空,如果下一行是最後一行則立刻退出,之後命令不在執行。流程大致如下:
sed基礎

s 搜尋替換命令

s命令是我們最常用的命令,"s"命令的語法格式為:其中"/"可以替換成任意其他單個字元。 s/REGEXP/REPLACEMENT/FLAGS
它使用 REGEXP去匹配行,將匹配到的那部分字元替換成 REPLACEMENT。FLAGS是 "s"命令的修飾符,常見的有"g"、"p"和"i"或"I"。
"g":表示替換行中所有能被 REGEXP匹配的部分。不使用 g時,預設只替換行中 的第一個匹配內容。此外,"g"還可以替換成一個數值 N,表示只替換行中第 N個 被匹配的內容。
"p":輸出替換後模式空間中的內容。
"i"或"I":REGEXP匹配時不區分大小寫。

[root@lbaby ~]# sed -n 's/root/&super/p' /etc/passwd
rootsuper:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/rootsuper:/sbin/nologin
不使用g的時候值替換行中匹配到的第一個

[root@lbaby ~]# sed -n 's/root/&super/pg' /etc/passwd
rootsuper:x:0:0:rootsuper:/rootsuper:/bin/bash
operator:x:11:0:operator:/rootsuper:/sbin/nologin

插入追加修改

[a|i|c] string
將string佇列到記憶體中,當有輸出動作的時候追上輸出流進行追加,插入或替換然後進行輸出

sed '/root/asuperman' /etc/passwd      在匹配到的行的下一行新增指定內容
[root@lbaby ~]# sed '/root/asuperman' /etc/passwd
root:x:0:0:root:/root:/bin/bash
superman
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
superman
……

sed '/root/isuperman' /etc/passwd      匹配到的行的上一行新增
[root@lbaby ~]# sed '/root/isuperman' /etc/passwd
superman
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
superman
operator:x:11:0:operator:/root:/sbin/nologin

sed '/root/csuperman' /etc/passwd      代替匹配到的行
[root@lbaby ~]# sed '/root/csuperman' /etc/passwd
superman
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
superman

sed高階命令

之前我們用到的sed命令都是一行一行的進行處理文字的,不過有些時候單行處理可能並不能滿足我們的需要,所以sed還提供了多行模式,多行模式的命令主要有NPD這三個,
N:讀取匹配到的行的下一行追加至模式空間
P:列印模式空間開端至n內容,並追加到預設輸出之前
D:如果模式空間包含換行符,則刪除直到第一個換行符的模式空間中的文字, 並不會讀取新的輸入行,而使用合成的模式空間重新啟動迴圈。如果模式空間 不包含換行符,則會像發出d命令那樣啟動正常的新迴圈
首先還是先看一下N命令的大致流程圖,P和D命令在懂了N命令之後也容易理解。

需要注意的是,之所以叫多行模式是因為可以存放不止兩行,如下範例:

[root@VM_161_150_CentOS ~]# cat /etc/passwd |sed -n '2{N;p}'
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

### 讀取第二行的下一行,然後輸出模式空間中的內容,此時模式空間中有兩行

[root@VM_161_150_centos ~]# cat /etc/passwd |sed -n '2{N;N;N;p}'
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

### 使用多個N命令可以讀取多行進模式空間

模式空間

除了模式空間,sed命令還有另外一個空間叫保持空間,其實保持空間很容易理解,之前我們說sed在處理文字的時候都是在模式空間中進行,但有時候有些複雜的操作單一的模式空間可能無法滿足我們的需求於???就有了模式空間,模式空間你可以看作是模式空間的翻版,但是這個空間通常是空閒的,並不處理資料,只在有需要的時候和模式空間進行一些必要的資料交換。下面是模式空間中的常用命令。
h: 把模式空間中的內容覆蓋至保持空間中
H:把模式空間中的內容追加至保持空間中
g: 從保持空間取出資料覆蓋至模式空間
G:從保持空間取出內容追加至模式空間
x: 把模式空間中的內容與保持空間中的內容進行互換
打個比方,假如你有兩個杯子,
h 就相當於吧二個杯子中的東西替換為第一個杯子中的,
H就相當於把第一個杯子中的東西放到第二個杯子中,並且第二個杯子中的東西還在,
g和h相似,不過是反了過來吧第一個杯子中的東西替換為第二個杯子中的,
G也是和H類似,x就相當於把兩個杯子中的東西進行了交換。

下面通過幾個範例演示一下

[root@VM_161_150_centos ~]# seq 1 6| sed -n '1,2H;4p;5{x;p}'
4

1
2

解釋一下,-n是不顯示預設輸出內容,1,2H是將前兩行追加至保持空間,4p顯示第四行,5{x;p}是在第五行的時候交換保持空間和模式空間中的內容並且輸出。注意輸出中的空行,這是因為H命令追加的時候是新增換行符,由於保持空間預設是空的,所以新增換行符之後就多了一個空行。以用下面的命令先往保持空間覆蓋一行然後追加。

[root@VM_161_150_centos ~]# seq 1 6| sed -n '1h;2H;4p;5{x;p}'
4
1
2

第一個迴圈結束之後:模式空間為空,保持空間為第一行內容
第二個迴圈,將第二行追加到模式空間,此時模式空間為兩行內容
第三個迴圈,沒有匹配內容,不執行操作,模式空間和保持空間內容不變
第四個迴圈,讀取第四行並輸出,保持空間內容不變
第五個迴圈,讀入第五行,然後和保持空間中的內容交換,之後輸出。

本文永久更新連結地址https://www.linuxidc.com/Linux/2018-05/152196.htm


IT145.com E-mail:sddin#qq.com