三劍客之老二sedlinux |
咱們都知道,在Linux中一切皆文件,好比配置文件,日誌文件,啓動文件等等。若是咱們相對這些文件進行一些編輯查詢等操做時,咱們可能會想到一些vi,vim,cat,more等命令。可是這些命令效率不高,這就比如一塊空地準備搭建房子,請了10個師傅拿着鐵鍬挖地基,花了一個月的時間才挖完,而另一塊空地則請了個挖土機,三下五除二就搞定了,這就是效率。而在linux中的「挖土機」有三種型號:頂配awk,中配sed,標配grep。使用這些工具,咱們可以在達到一樣效果的前提下節省大量的重複性工做,提升效率。面試
接下來咱們就看一下sed的詳細說明正則表達式
sed 是Stream Editor(字符流編輯器)的縮寫,簡稱流編輯器。什麼是流?你們能夠想象如下流水線,sed就像一個車間同樣,文件中的每行字符都是原料,運到sed車間,而後通過一系列的加工處理,最後從流水線下來就變成貨物了。shell
sed是非交互式的編輯器。它不會修改文件,除非使用shell重定向來保存結果。默認狀況下,全部的輸出行都被打印到屏幕上。express
sed編輯器逐行處理文件(或輸入),並將結果發送到屏幕。具體過程以下:首先sed把當前正在處理的行保存在一個臨時緩存區中(也稱爲模式空間),而後處理臨時緩衝區中的行,完成後把該行發送到屏幕上。sed每處理完一行就將其從臨時緩衝區刪除,而後將下一行讀入,進行處理和顯示。處理完輸入文件的最後一行後,sed便結束運行。sed把每一行都存在臨時緩衝區中,對這個副本進行編輯,因此不會修改原文件。vim
固然上圖中的文件內容能夠是來自文件,也能夠直接來自鍵盤或者管道等標準輸入,最後的結果默認狀況下是顯示到終端的屏幕上,可是也能夠輸出到文件中。緩存
之前工廠中沒有流水線時,生產一件商品須要十幾個工種互相配合,這樣下來利潤過低,後來就有了流水線,生產一件商品雖然仍是有十幾道工序,但都是機器化生產,工人只是輔助做用,這樣利潤就大大提升了,產量也大大提升了。bash
編輯文件也是這樣,之前咱們修改一個配置文件,須要移動光標到某一行,而後添加點文字,而後又移動光標到另外一行,註釋點東西.......可能修改一個配置文件下來須要花費數十分鐘,還有可能改錯了配置文件,又得返工。這仍是一個配置文件,若是數十個數百個呢?所以當你學會了sed命令,你會發現利用它處理文件中的一系列修改是頗有用的。只要想到在大約100多個文件中,處理20個不一樣的編輯操做能夠在幾分鐘以內完成,你就會知道sed的強大了。less
Sed命令是操做,過濾和轉換文本內容的強大工具。經常使用功能有增刪改查(增長,刪除,修改,查詢),其中查詢的功能中最經常使用的2大功能是過濾(過濾指定字符串),取行(取出指定行)。ssh
sed版本是GNU開源版本的,個人實驗環境是CentOS6.8系統,內核版本是2.6.32-642.el6.x86_64
[root@kaile /]# cat /etc/redhat-release #查看Linux版本
CentOS release 6.8 (Final)
[root@kaile /]# uname -r #查看內核版本
2.6.32-642.el6.x86_64
[root@kaile /]# sed --version #使用的sed版本
GNU sed 版本 4.2.1
sed [options] [sed -commands][input -file]
sed [選項] 【sed命令】【輸入文件】
說明:
1 注意sed軟件以及後面選項,sed命令和輸入文件,每一個元素之間都至少有一個空格。
2 爲了不混淆,本文稱呼sed爲sed軟件。sed -commands(sed命令)是sed軟件內置的一些命令選項,爲了和前面的options(選項)區分,故稱爲sed命令
3 sed -commands 既能夠是單個sed命令,也能夠是多個sed命令組合。
4 input -file (輸入文件)是可選項,sed還可以從標準輸入如管道獲取輸入。
Sed軟件從文件或管道中讀取一行,處理一行,輸出一行;再讀取一行,再處理一行,再輸出一行....
一次一行的設計使得sed軟件性能很高,sed在讀取很是龐大的文件時不會出現卡頓的想象。你們都用過vi命令,用vi命令打開幾十M或更大的文件,會發現有卡頓現象,這是由於vi命令打開文件是一次性將文件加載到內存,而後再打開,所以卡頓的時間長短就取決於從磁盤到內存的讀取速度了。並且若是文件過大的話還會形成內存溢出現象。Sed軟件就很好的避免了這種狀況,打開速度很是快,執行速度也很快。
現有一個文件person.txt,共有五行文本,sed命令讀入文件person.txt的第一行「101,zhaokai,CEO」,並將這行文本存入模式空間(sed軟件在內存中的一個臨時緩存,用於存放讀取到的內容,比喻爲工廠流水線的傳送帶。)
1,判斷第1行是不是須要處理的行,若是不是要處理的行就從新從文件讀取下一行,若是是要處理的行,則接着往下走。
2,對模式空間的內容執行sed命令,好比a(追加),i(插入),s(替換)...
3,將模式空間中通過sed命令處理後的內容輸出到屏幕上,而後清空模式空間
4,讀取下一行文本,而後從新執行上面的流程,直到文件結束
模式空間(pattern space):是sed軟件從文本讀取一行文本而後存入的緩衝區(這個緩衝區是在內存中的),而後使用sed命令操做模式空間的內容。
保持空間(hold space):是sed軟件另一個緩衝區,用來存放臨時數據,也是在內存中,可是模式空間和保持空間的用途是不同的。Sed能夠交換保持空間和模式空間的數據,可是不能在保持空間上執行普通的sed命令,也就是說咱們能夠在保持空間存儲數據。
option[選項] |
解釋說明(帶*的爲重點) |
-n |
取消默認的sed軟件的輸出,常與sed命令的p連用。* 取消模式空間的默認輸出 |
-e |
一行命令語句能夠執行多條sed命令 sed '2d';'1i ceshi' test.txt |
-f |
選項後面能夠接sed腳本的文件名 |
-r |
使用擴展正則表達式,默認狀況sed只識別基本正則表達式* 擴展正則 +連續重複前面一個字符或多個字符 ()分組替換 括號裏面的字符保護起來後向引用 |
-i |
直接修改文件內容,而不是輸出到終端,若是不使用-i選項sed軟件只是修改在內存中的數據,並不會影響磁盤上的文件* |
a |
追加,在指定行後添加一行或多行文本* |
c |
取代指定的行 替換指定行 sed '1c ceshi' test.txt |
d |
刪除指定的行* $最後一行 sed '1,5d' 刪除一到5行內容 sed '5,$' 刪除5到最後一行 |
D |
刪除模式空間的部份內容,直到遇到換行符\n結束操做,與多行模式相關 |
i |
插入,在指定行前添加一行或多行文本* |
h |
把模式空間的內容複製到保持空間 |
H |
把模式空間的內容追加到保持空間 |
g |
把保持空間的內容複製到模式空間 |
G |
把保持空間的內容追加到模式空間 |
x |
交換模式空間和保持空間的內容 |
l |
打印不可見的字符 |
n |
清空模式空間的內容並讀入下一行 |
N |
不清空模式空間,並讀取下一行數據並追加到模式空間* |
p |
打印模式空間內容,一般p會與選項-n一塊兒使用* |
P(大寫) |
打印模式空間的內容,直到遇到換行符\n結束操做 |
q |
退出Sed |
r |
從指定文件讀取數據 |
s |
取代,s#old#new#g==>這裏g是s命令的替代標誌,注意和g命令區分。s命令替換* |
w |
另存,把模式空間的內容保存到文件中 |
y |
根據對應位置轉換字符 |
:label |
定義一個標籤 |
b label |
執行該標籤後面的命令 |
t |
若是前面的命令執行成功,那麼就跳轉到t指定的標籤處,繼續往下執行後續命令。不然,仍然繼續正常的執行流程 |
特殊符號 |
解釋說明(帶*的爲重點) |
! |
對指定行之外的全部行應用命令* |
= |
打印當前行行號 |
~ |
「First~step」表示從First行開始,以步長Step遞增 sed '1~3' |
& |
表明被替換的內容 |
; |
實現一行命令語句能夠執行多條sed命令* |
{} |
對單個地址或地址範圍執行批量操做 |
+ |
地址範圍中用到的符號,作加法運算 |
爲了更好的測試sed命令的用法,咱們須要準備好下面的測試文件。
[root@kaile ~]# cat>person.txt<<EFO
> 101,zhaokai,CEO
>102,zhangyang,CTO
> 103,Alex,COO
> 104,yy,CFO
> 105,feixue,CIO
> EFO #EFO必須成對出現,表示終止輸入
命令說明:使用一條cat命令建立多行文本,文件包含上面的內容,後面的操做都會使用這個文件。
接下來我來教你們第一式招法-->往文件指定位置追加或插入指定文本。
這個功能很是有用,好比咱們平時往配置文件寫入幾行文本,最經常使用的是vi或vim命令,可是這2個命令是一種交互式的命令,還須要咱們在vi/vim編輯器界面輸入字符串而後保存退出,操做有些繁瑣可是還能用。可是當咱們學會了Shell腳本後,咱們就會發如今腳本中不能正常使用vi或vim命令,爲何呢?同窗們請自行體驗。
咱們學習Shell腳本主要是爲了解放咱們的雙手,執行一個腳本,而後自動往文件中寫入數據,不須要咱們再動手。所以咱們想到了sed軟件,它可以幫助咱們實現目的。
這裏咱們須要用到2個sed命令,分別是:
「a」:追加文本到指定行後,記憶方法:a的全拼是apend,意思是追加。
「i「:插入文本到指定行前,記憶方法:i的全拼是insert,意思是插入。
首先咱們看一下單行增長的用法,說白了就是在文件中增長一行文本,咱們之前學過echo命令能夠在文件的末尾追加文本,比較簡單,可是咱們還有其餘的複雜需求,好比在第10行插入一行數字等等,這裏就須要sed出馬了。咱們來看一下下面的例子,同窗也跟着例子一塊兒練習,命令只有多練纔會熟悉,光看永遠是學不會的。
#在文件person.txt 文件第一行追加 dan,CEO
[root@kaile ~]# sed '1a dan,CEO' person.txt # 1表明一行 a 表明追到到指定行號
101,zhaokai,CEO
dan,CEO #追加的內容
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
##在文件person.txt 文件第五行插入 oldboy
[root@kaile ~]# sed '5i oldboy' person.txt
101,zhaokai,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
oldboy
105,feixue,CIO
命令行詳解:
首先咱們看一下命令的結果,咱們能夠看到原來的第二行「102,zhangyang,CTO」 前面插入了新的一行爲「dan,CEO」,原來的第2行變成第3行了。
接下來咱們解讀一下sed語句的結構,sed打頭,而後接上空格(空格個數不限,但至少要有一個!)在空格後面,咱們先敲上一對單引號(「)而後退格在單引號中協商‘dan,CEO’。
5表明指定對第5行操做,其餘的行忽略
i表明插入的意思,5i即在第5行前插入文本
5i後面加上空格,而後跟上你想要插入的文本便可
[root@kaile~]# cat person.txt
101,zhaokai,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
#單引號--文本內容原封不動插入
[root@kaile ~]# sed '2i $LANG' person.txt
101,zhaokai,CEO
$LANG
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
#不加引號,linux沒法辨認空格,不會把有空格的命令當成一條命令來執行
[root@kaile ~]# sed 2i $LANG person.txt
sed:-e 表達式 #1,字符 2:指望在「a」, 「c」, 「i」以後有「\」
#雙引號--變量$LANG被解析之後在看成文本進行插入
[root@kaile ~]# sed "2i $LANG"person.txt
101,zhaokai,CEO
zh_CN.GB2312
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
sed中到底使用單引號仍是雙引號?
雙引號:把雙引號的內容輸出出來;若是內容中有命令,變量等,會先把命令,變量解析出結果,而後再輸出最終內容來。雙引號內命令或變量的寫法爲`命令或變量`或$(命令或變量)
[root@kaile ~]# echo "$LANG"
zh_CN.GB2312
單引號:所見即所得,將單引號內的內容原樣輸出,阻止全部字符的轉義
[root@kaile ~]# echo '$LANG'
$LANG
不加引號:不會將含有空格的字符串視爲一個總體輸出,若是內容中有命令,變量等,會先把命令,變量解析出結果,而後再輸出最終內容來,若是字符串含有空格等特殊字符,則不能完整輸出,則需改加雙引號。
[root@kaile ~]# echo ceshi
ceshi
[root@kaile~]# echo $LANG
zh_CN.GB2312
倒引號(反引號Esc鍵下方):進行命令的替換,在倒引號內部的shell命令將會被執行,其結果輸出代替用倒引號括起來的文本。
若是引號裏面是普通字符串的話,你能夠任意使用單引號或者雙引號:
若是引號裏面是變量或者帶反引號的命令的話,你想要變量解析的結果或者命令執行的結果,那就使用雙引號;你想要引號內的原樣字符串,那就使用單引號。
只要你們理解上面的用法,明白本身想要什麼,那麼你想用什麼引號就用什麼引號。
其實就二選一,非此即彼,這個不行就試試那個。
前面學習的內容已經實現了往文件追加或插入單行文本,可是還有插入多行文本的需求,咱們也學習過cat命令可以往文件中追加多行文本。
[root@kaile ~]# cat test.txt
welcome to my blog.http://kaile.blog.51cto.com
空行
if you like my blog\'s contents,pls support me.
空行
空行
bye!boys and girls.
命令說明:以上就是cat的生產環境經常使用的生成或爲文件追加內容的方法,請不要忽略上文中的空行。另外,若是內容中有單引號,$符號等特殊符號做爲內容時要用「\」轉義。
[root@kaile ~]# echo 'zhao';echo 'kai' ; 分割符 鏈接兩條命令,而後輸出結果爲2行
zhao
kai
[root@kaile ~]# echo -e 'zhao\nkai' #換行符\n
zhao
kai
學習完換行符,咱們看一下sed命令如何使用
[root@kaile ~]# sed '2axiaokai\nxiaodong\nxiaoyue' person.txt
101,zhaokai,CEO
102,zhangyang,CTO
xiaokai
xiaodong
103,Alex,COO
104,yy,CFO
105,feixue,CIO
命令行分析:
咱們首先粗略掃一眼這個命令語句,能夠發現命令結構是和單行增長文本是幾乎沒有區別的。
而後咱們看一下命令的結果,咱們能夠看到原來的第二行「102,zhangyang,CTO」後面追加了2行文本「xiaokai,」和「xiaodong」。
接下來咱們解讀一下sed語句的結構,sed軟件打頭,而後接上空格,在空格後面,咱們先敲上一對單引號(' '),而後退一格在單引號中寫上‘2a xiaokai\nxiaodong’。
2表明指定對第2行操做,其餘的行忽略;
a表明追加的意思,2a即在第2行後追加文本;
2a後面加上空格,而後跟上你想要插入的多行文本便可。這裏的每行文本使用「\n」鏈接就能夠寫成一行了。
刪除指定行文本。
這個功能也是很是得有用,好比咱們想刪除文件中的某些行,之前最經常使用的是vi或vim命令,但如今咱們知道了sed命令,就應該使用這個高逼格的命令完成任務了。
這裏咱們須要用到1個sed命令;
「d」:刪除文本,記憶方法:d的全拼是delete,意思是刪除。
由於刪除功能比較簡單,所以咱們結合地址範圍一塊兒說明。咱們前面學過sed命令能夠對一行文本爲目標進行處理(在單行先後增長一行或多行文本),接下來咱們看一下如何對多行文本爲目標操做。
sed軟件能夠對單行或多行文本進行處理。若是在sed命令前面不指定地址範圍,那麼默認會匹配全部行。
用法:n1[,n2]{sed-commands}
地址用逗號分隔開,n1,n2能夠用數字,正則表達式,或者兩者的組合表示。
地址範圍 |
含義 |
10{sed-commands} |
對第10行操做
sed -n '10p' person.txt sed '10d' person.txt |
10,20{sed-commands} |
對10到20行操做,包括第10,20行
sed '10,20d' person.txt #10行20行刪除 sed -n '10,20p' person.txt #10到20行打印輸出 |
10,+20{sed-commands} |
對10到30(10+20)行操做,包括第10,30行
如:sed -n '10,+20p' person.txt |
1~2{sed-commands} |
對1,3,5,7.....行操做 奇數偶數
sed '1~3d' person.txt 刪除奇數 |
10,\${sed-commands} |
對10到最後一行($表明最後一行)操做,包括第10行 sed -n '10,$p' person.txt |
/kaile/{sed-commands} |
對匹配kaile的行操做 |
/kaile/,/Alex/{sed-commands} |
對匹配kaile的行到匹配Alex的行操做 |
/kaile/,\${sed-commands} |
對匹配kaile的行到最後一行操做 |
/kaile/,10{sed-commands} |
對匹配kaile的行到第10行操做, |
1,/Alex/{sed-commands} |
對第1行到匹配Alex的行操做 |
/kaile/,+2{sed-commands} sed '/2/,+2d' person.txt |
對匹配kaile的行到其後的2行操做 |
下面用具體的例子演示一下,測試文件仍是person.txt
[root@kaile~]
# sed 'd' person.txt
[root@kaile~]
#
命令說明:若是在sed命令前面不指定地址範圍,那麼默認會匹配全部行,而後使用d命令刪除功能就會刪除這個文件的全部內容
[root@kaile~]
# sed '2d' person.txt
101,kaile,CEO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
命令說明:這個單行刪除想必你們能理解,指定刪除第2行的文本102,zhangyang,CTO
[root@kaile~]
# sed '2,5d' person.txt
101,kaile,CEO
命令說明:‘2,5d’指定刪除第2行到第5行的內容,d表明刪除操做。
ok,上面咱們實驗完了數字地址範圍,接下來咱們實驗一下正則表達式的地址範圍,雖說可使用正則表達式,可是咱們仍是習慣寫出完整的匹配字符串,達到精確匹配的目的。
[root@kaile~]
# sed '/zhangyang/d' person.txt
101,kaile,CEO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
命令說明:
在sed軟件中,使用正則的格式和awk同樣,使用2個」/「包含指定的正則表達式,即「/正則表達式/」。
固然也可使用兩個正則表達式,以下例所示。
[root@kaile~]
# sed '/kaile/,/Alex/d' person.txt
104,yy,
CFO
105,feixue,
CIO
命令說明:這是正則表達式形式的多行刪除,也是以逗號分隔2個地址,最後結果是刪除包含「kaile」的行到包含「Alex」的行
[root@kaile~]
# sed '3,$d' person.txt
101,kaile,CEO
102,zhangyang,CTO
命令說明:學過正則表達式後咱們知道「$」表明行尾,可是在sed中就有一些變化了,「$」在sed中表明文件的最後一行。所以本例子的含義是刪除第3行到最後一行的文本,包含第3行和最後一行,所以剩下第1,2行的內容。
接下來咱們看一些特殊狀況。
[root@kaile~]
# sed '/kaile/,3d' person.txt
104,yy,
CFO
105,feixue,
CIO
命令說明:這個例子是刪除包含「kaile」的行到第3行的內容。但這種組合有一個比較特殊的狀況,若是前3行以外還有這個「kaile」字眼,sed軟件仍是會找他「麻煩」,請看下面例子。
[root@kaile~]
# sed '$a 106,kaile,CMO' person.txt
101,kaile,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
106,kaile,CMO
命令說明:爲了避免形成同窗們實驗文本改來改去致使不一樣意,所以我用上面的命令語句只是臨時修改內存數據,而後經過管道符號傳給sed軟件。
[root@kaile~]
# sed '$a 106,kaile,CMO' person.txt | sed '/kaile/,3d'
104,yy,
CFO
105,feixue,
CIO
命令說明:從命令結果咱們能夠看到,不只是第1行(101,kaile,CEO)到第3行(103,ALex,COO)被刪除了,並且最後一行(106,kaile,CMO)也被刪除了。所以咱們能夠得出一個小結論,sed軟件使用正則表達式會找出全部匹配的行,即便是有數字地址限制。
再來看一個特殊狀況。
[root@kaile~]
# sed '2,/O/d' person.txt
101,kaile,CEO
104,yy,CFO
105,feixue,CIO
命令說明:
從第2行開始刪除到含字母O的行結束,可是咱們發現第3,4,5行都含有字母O,命令結果顯示只刪除了第2,3行,屬於最短刪除。這個怎麼理解?
仍是能夠從上面命令執行流程圖理解,從第2行開始循環,sed軟件第一次遇到字母O(第三行)就認爲循環結束了。
[root@kaile~]
# sed '2,/o/d' person.txt
101,kaile,CEO
命令說明:
從第2行開始刪除,可是後面文本沒有字母O,所以一直循環下去,直到文本結束,sed軟件自動終止。
你們看完上面的例子是否是一臉懵逼,其實很簡單。在工做中咱們最經常使用的仍是數字地址這種精確匹配方式,像上面的正則地址或混合地址這種模糊匹配用的比較少,瞭解便可。
格式:「First~step」表示從開始,以步長step遞增,這個在數學中叫作等差數列
例子:
1~2 匹配1,3,5,7.....#-->用於只輸出奇書行,大夥仔細觀察一下每一個數字的差值。
2~2 匹配2,4,6,8....#-->用於只輸出偶數行
1~3 匹配1,4,7,10.....
2~3 匹配2,5,8,11.....
[root@kaile~]
# seq 10
1
2
3
4
5
6
7
8
9
10
命令說明:seq命令可以生成從1到10的數字序列。
[root@kaile~]
# seq 10 | sed -n '1~2p'
1
3
5
7
9
命令說明:
上面的命令主要驗證特殊符號「~」的效果,其餘sed命令用法n和p請見後文詳解,你們只須要知道這個命令能夠將「1~2」指定的行顯示出來便可。
上面例子測試了「1~2」的效果,你們也能夠手動測試一下「2~2」,「1~3」,「2~3」,看一下他們的結果是否是符合等差數列。
補充小知識:
若是你們想生成奇數數列,其實上面的方法是爲了舉例,並非一個很好的方法,由於seq命令自帶這種功能。
[root@kaile~]
# seq 1 2 10
1
3
5
7
9
命令說明:seq命令格式seq起始值 公差 結束值
再來一例:
[root@kaile~]
# sed '1~2d' person.txt
102,zhangyang,CTO
104,yy,CFO
命令說明:「1~2」這是指定行數的另外一種格式,從第1行開始以步長2遞增的行(1,3,5),所以刪掉第1,3,5行,即全部的奇數行。
命令說明:seq命令格式seq起始值 公差 結束值
再來一例:
[root@kaile1~]
# sed '1~2d' person.txt
102,zhangyang,CTO
104,yy,CFO
命令說明:「1~2」這是指定行數的另外一種格式,從第1行開始以步長2遞增的行(1,3,5),所以刪掉第1,3,5行,即全部的奇數行。
[root@kaile1~]
# sed '1,+2d' person.txt
104,yy,
CFO
105,feixue,
CIO
命令說明:這實際上是作個加法運算,‘1,+2d’==>刪除第1行到第3(1+2)行的文本。
上面是特殊符號「+」的用法,你們知道便可。
感嘆號「!」咱們在不少命令裏都接觸過,大部分都是取反的意思,在sed中也不例外。
[root@kaile1 ~]# sed '2,3!d' person.txt
102,zhangyang,CTO
103,Alex,COO
命令說明:在地址範圍「2,3」後面加上「
!」,若是不加「!」表示刪除第2行和第3行,結果以下面的例子所示,而後加上「!」的結果就是除了第2行和第3行之外的內容都刪除,這個方法能夠做爲顯示文件的第2,3行題目的補充方法。
[root@kaile1 ~]# sed '2,3d' person.txt
101,kaile,CEO
104,yy,CFO
5105,feixue,CIO
這是一道企業面試題,很簡單,就是把包含kaile字符串的行刪除掉便可。咱們能夠用「grep -v」取反獲得咱們想要的結果,可是這裏咱們使用sed軟件實現。
[root@kaile1 ~]# sed '/kaile/d' person.txt
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
你們如今已經學完了sed軟件2大招式,是否是很厲害!固然後面還有更厲害的--->改.在學習linux時,咱們最多見的操做就是改配置文件,改參數等等,並且更妙的是前面咱們學習過的增長和刪除其實均可以用咱們準備要學的修改變相實現。
首先說一下按行替換,這個功能用的不多,因此你們瞭解便可。這裏用到的sed命令是:
「c」:用新行取代舊行,記憶方法:c的全拼是change,意思是替換。
例子:
[root@kaile ~]# sed '2c 106,dandan,CSO' person.txt
101,kaile,CEO
106,dandan,CSO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
命令說明:使用sed命令c將原來第2行「102,zhangyang,CTO」替換成「106,dandan,CSO」,整行替換
接下來講的這個功能,有工做經驗的同窗應該很是的熟悉,由於使用sed軟件80%的場景就是使用替換功能。
這裏用到的sed命令,選項:
「s」:單獨使用-->將每一行中第一處匹配的字符串進行替換==>sed命令
「g」:每一行進行所有替換-->sed命令s的替換標誌之一(全局替換),非sed命令。
「-i」:修改文件內容-->sed軟件的選項,注意和sed命令i區別。
sed -i 's/目標內容/替換內容/g'kaile.log
sed -i 's#目標內容#替換內容#g'
1,兩邊是引號,引號裏面的兩邊分別爲s和g,中間是三個同樣的字符/或#做爲定界符。字符#能在替換內容包含字符/有助於區別。定界符能夠是任意字符如:或|等,但當替換內容包含定界符時,須要轉義\:或\|.通過長期實踐,建議你們使用#做爲定界符。
2,定界符/或#,第一個和第二個之間的就是被替換的內容,第二個和第三個之間的就是替換後的內容。
3,s#目標內容#替換內容#g ,「目標內容」能用正則表達式,但替換內容不能用,必須是具體的。由於替換內容使用正則的話會讓sed軟件無所適從,它不知道你要替換什麼內容。
4,默認sed軟件是對模式空間(內存中的數據)操做,而-i選項會更改磁盤上的文件內容。
例子:
[root@kaile~]
# sed 's#zhangyang#dandan#g' person.txt
101,kaile,CEO
102,dandan,CTO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
命令說明:將須要替換的文本「zhangyang」放在第一個和第二個「#」之間,將替換後的文本「dandan」放在第二個核第三個「#」之間。結果爲第二行的「zhangyang」替換爲「dandan」。
修改文件:
[root@kaile~]
# cat person.txt
101,kaile,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
命令說明:從上面命令的結果咱們就知道sed命令默認不會修改文件的內容
[root@kaile~]
# sed -i 's#zhangyang#dandan#g' person.txt
命令說明:若是想真正的修改文件內容,咱們就須要使用選項「-i」,這個要和sed命令「i」區分開來。同時咱們能夠發現命令執行後的結果是沒有任何輸出的。
[root@kaile~]
# cat person.txt
101,kaile,CEO
102,dandan,CTO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
命令說明:當咱們再次查看這個文件時,咱們就發現這個文件已經被修改爲功了。所以你們之後若是使用替換功能時,應該首先不用選項「-i」測試一下,確保操做無誤,最後使用「-i」修改文件
還原測試文件:
[root@kaile~]
# sed -i 's#dandan#zhangyang#g' person.txt
命令說明:還原測試文件,這一步你們不要忘了執行,否則後面就跟不上步驟了
前面咱們學過的模型可以將文件中全部知足條件的文本進行操做,可是咱們也會碰到指定行精確修改配置文件的需求,由於這樣能夠避免修改多了地方。
[root@kaile~]
# sed '3s#0#9#' person.txt
101,kaile,CEO
102,zhangyang,CTO
193,Alex,COO
104,yy,
CFO
105,feixue,
CIO
命令說明:
前面學習的例子在sed命令「s」前沒有指定地址範圍,所以默認是對全部行進行操做。
而這個案例要求只將第3行的0換成9,這裏就用到了咱們前面學過的地址範圍知識,在sed命令「s」前加上「3」就表明對第3行進行替換
變量替換其實和前面的文本替換是同樣的,就是具體的文本變成了變量,同時要求你們對引號的用法要有清晰的理解,所以對雙引號和單引號的區別不太理解的同窗,請往前面翻頁到【引號的區別總結】再次複習一下。
[root@kaile~]
# cat >test.txt<<KOF #再新建一個簡單的測試文本
> a
> b
> a
>KOF
[root@kaile~]
# cat test.txt
a
b
a
[root@kaile~]
# x=a #->設置變量x並賦值a
[root@kaile~]
# y=b #-> 設置變量y並賦值b
[root@kaile~]
# echo $x
a
[root@kaile~]
# echo $x $y
a b
命令說明:打印變量x,y驗證一下,須要使用$符號引用變量
不使用引號:
[root@kaile ~]# sed s#$x#$y#g test.txt
b
b
b
命令說明:使用變量進行替換,從執行結果中咱們能夠發現替換成功了,test.txt文件中全部的a都替換成了b。同時咱們能夠發現s#$x#$y#g沒有使用引號,固然這種寫法並非特別標準。
[root@kaile ~]# sed 's#'$x'#'$y'#g' test.txt
b
b
b
命令說明:表面看起來單引號是能夠用的,但其實這裏用了障眼法,在大家眼中分段‘$x’和'$y',但其實分段是‘s#’和‘#’和‘#g’,因此$x和$y並無被引號擴起來,和上面的例子就同樣了。
使用eval命令:
[root@kaile ~]# eval sed 's#$x#$y#g' test.txt
b
b
b
命令說明:這裏給你們擴展一個Linux內置命令eval,這個命令能讀入變量,並將他們組合成一個新的命令,而後執行。首先eval會解析變量$x和變量$y,最後達到的效果和雙引號是同樣的。
擴展:最快速的獲取IP地址的方法
[root@kaile ~]# hostname-I
192.168.197.133
sed軟件的()的功能能夠記住正則表達式的一部分,其中,\1爲第一個記住的模式即第一個小括號中的匹配內容,\2第二個記住的模式,即第二個小括號中的匹配內容,sed最多能夠記住9個。
例:echo "I am kaileteacher."若是想保留這一行的單詞kaile,刪除剩下部分,使用圓括號標記想保留的部分。
[root@kaile~]
# echo "I am kaile teacher." | sed 's#^.*am\([a-z]\+\) tea.*$#\1#g'
kaile
[root@kaile~]
# echo "I am kaile teacher." | sed -r 's#^.*am([a-z]+) tea.*$#\1#g'
kaile
[root@kaile~]
# echo "I am kaile teacher." | sed -r 's#I (.*)(.*) teacher.#\1\2#g'
amkaile
命令說明:
sed若是不加-r後綴,那麼默認不支持擴展正則表達式,須要\符號進行轉義。小括號的做用是將括號裏的匹配內容進行分組以便在第2和第3個#號之間進行sed的反向引用,\1表明引用第一組,\2表明引用第二組
再來看個題目:請執行命令取出linux中的eth0的IP地址?
[root
@kaile ~]# ifconfig eth0 | sed -n
'2p'
inet addr:
192.168.197.133
Bcast:
192.168.197.255
Mask:
255.255.255.0
[root
@kaile ~]# ifconfig eth0 | sed -n
'2p' | sed -r
's#^.*addr:(.*)
Bcast:.*$#\
1#g'
192.168.197.133
進行組合
[root
@kaile ~]# ifconfig eth0 | sed -rn
'2s#^.*addr:(.*)
Bcast:.*$#\
1#gp'
192.168.197.133
命令說明:
這道題是須要把ifconfig eth0執行結果的第2行的IP地址取出來,上面答案的思路是用IP地址來替換第2行的內容。
[root
@kaile ~]# chkconfig --list | egrep-v
"sshd|crond|rsyslog|sysstat|network" | awk '{print $
1}' |sed -r
's#^(.*)#chkconfig \
1 off#g' |bash
這題也能夠應用awk直接一步到位
[root
@kaile ~]# chkconfig --list | egrep-v
"sshd|crond|network|rsyslog|sysstat" | awk '{print
"chkconfig",$
1,
"off"}' | bash
這是一個特殊技巧,在適合的場景使用特別方便。下面用特殊符號「&」與分組替換一塊兒使用,進行對比。
[root@kaile~]# sed -r
's#(.*),(.*),(.*)#& ----- \1 \2 \3#' person.txt
101,kaile,CEO
----- 101 kaile CEO
102,zhangyang,CTO
----- 102 zhangyang CTO
103,Alex,COO
----- 103 Alex COO
104,yy,CFO
----- 104 yy CFO
105,feixue,CIO
----- 105 feixue CIO
命令說明:
1,這裏將分組替換和&符號放在一塊兒對比
2,命令中的分組替換使用了3個小括號,每一個小括號分別表明每一行以逗號做爲分隔符的每一列。
3,上面命令的&符號表明每一行,即模型中‘s#目標內容#替換內容#g’的目標內容。
[root@kailechen]
# find ./ -name "*_finished.jpg"
./stu_102999_1_finished.jpg
./stu_102999_5_finished.jpg
./stu_102999_3_finished.jpg
./stu_102999_2_finished.jpg
./stu_102999_4_finished.jpg
要求用sed命令重命名,效果爲
stu_102999_1_finished.jpg==>stu_102999_1.jpg,即刪除文件名的_finished
解題思路:由於這是文件名,不能直接yongsed命令替換,所以還須要藉助mv命令重命名,格式爲:mvstu_102999_1_finished.jpg stu_102999_1.jpg.咱們須要拼湊這樣的格式,而後使用bash命令執行便可。
[root
@kaile chen]# find ./ -name
"*_finished.jpg" | sed -r
's#^(.*)_finished(.*)#\
1\
2#g'
./stu_102999_1.jpg
./stu_102999_5.jpg
./stu_102999_3.jpg
./stu_102999_2.jpg
[root
@kaile chen]# find ./ -name
"*_finished.jpg" | sed -r
's#^(.*)_finished(.*)#& \
1\
2#g'
./stu_102999_1_finished.jpg./stu_102999_1.jpg
./stu_102999_5_finished.jpg./stu_102999_5.jpg
./stu_102999_3_finished.jpg./stu_102999_3.jpg
./stu_102999_2_finished.jpg./stu_102999_2.jpg
./stu_102999_4_finished.jpg./stu_102999_4.jpg
[root
@kaile chen]# find ./ -name
"*_finished.jpg" | sed -r
's#^(.*)_finished(.*)#mv & \
1\
2#g'
mv./stu_102999_1_finished.jpg ./stu_102999_1.jpg
mv./stu_102999_5_finished.jpg ./stu_102999_5.jpg
mv./stu_102999_3_finished.jpg ./stu_102999_3.jpg
mv./stu_102999_2_finished.jpg ./stu_102999_2.jpg
mv./stu_102999_4_finished.jpg ./stu_102999_4.jpg
[root
@kaile chen]# find ./ -name
"*_finished.jpg" | sed -r
's#^(.*)_finished(.*)#mv & \
1\
2#g' |bash
[root
@kaile chen]# ls
stu_102999_1.jpg stu_102999_2.jpg stu_102999_3.jpg stu_102999_4.jpg stu_102999_5.jpg
命令說明:
1.「\1」表明前面「(^.*)」匹配內容,「&」表明「s# #」裏被替換的內容,這裏匹配到的是完整的文件名。
2.使用bash命令執行,bash命令執行標準輸入的語句,如同咱們在命令行輸入語句後敲回車。
學到這裏,你們能夠稍微喘口氣了,由於sed裏最經常使用最重要的咱們已經學完了,接下來咱們輕鬆的學完最後一招-->查看文本
這個功能也是很是得有用,好比咱們想查看文件中的某些行,之前最經常使用的是cat或more或less命令等,但這些命令有些缺點,就是不能查看指定的行。而咱們用了好久的sed命令就有了這個功能了。並且咱們前面也說過使用sed比其餘命令vim等讀取速度更快!
這裏咱們須要用到1個sed命令
「p」:輸出指定內容,但默認會輸出2次匹配的結果,所以使用-n選項取消默認輸出,記憶方法:p的全拼是print,意思是打印。
[root@kaile~]
# sed '2p' person.txt
101,kaile,CEO
102,zhangyang,CTO
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
[root@kaile~]
# sed -n '2p' person.txt
102,zhangyang,CTO
命令說明:選項-n取消默認輸出,只輸出匹配的文本,你們只須要記住使用命令p必用選項-n。
[root@kaile~]
# sed -n '2,3p' person.txt
102,zhangyang,CTO
103,Alex,COO
命令說明:查看文件的第2行到3行,使用地址範圍「2,3」。取行就用sed,最簡單
[root@kaile~]
# sed -n '1~2p' person.txt
101,kaile,CEO
103,Alex,COO
105,feixue,CIO
命令說明:打印文件的1,3,5行。~表明步長
[root@kaile~]
# sed -n 'p' person.txt
101,kaile,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
105,feixue,CIO
命令說明:不指定地址範圍,默認打印所有內容。
[root@kaile~]
# sed -n '/CTO/p' person.txt
102,zhangyang,CTO
命令說明:打印含CTO的行
[root@kaile~]
# sed -n '/CTO/,/CFO/p' person.txt
102,zhangyang,CTO
103,Alex,COO
104,yy,CFO
命令說明:打印含CTO的行到含CFO的行。
[root@kaile~]
# sed -n '2,/CFO/p' person.txt
102,zhangyang,CTO
103,Alex,COO
104,yy,
CFO
命令說明:打印第2行到含CFO的行。
[root@kaile~]
# sed -n '/feixue/,2p' person.txt
105,feixue,
CIO
命令說明:特殊狀況,前兩行沒有匹配到feixue,就向後匹配,若是匹配到feixue就打印此行。因此這種混合地址不推薦使用。
[root@kaile~]
# sed -rn '/kaile|yy/p' person.txt
101,kaile,CEO
104,yy,CFO
命令說明:
使用擴展正則「|」,爲了避免使用轉義符號「\」,所以使用-r選項開啓擴展正則表達式模式
[root@kaile~]
# cat person.txt
101,kaile,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
[root@kaile~]
# sed -i.bak 's#zhangyang#NB#g' person.txt
[root@kaile~]
# cat person.txt
101,kaile,CEO
102,NB,CTO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
[root@kaile~]
# cat person.txt.bak
101,kaile,CEO
102,zhangyang,CTO
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
命令行說明:
在-i參數的後邊加上.bak(.任意字符),sed會對文件進行先備份後修改
[root@kaile~]
# sed '=' person.txt
1
101,kaile,CEO
2
102,NB,CTO
3
103,Alex,COO
4
104,yy,
CFO
5
105,feixue,
CIO
命令說明:使用特殊符號「=」就能夠獲取文件的行號,這是特殊用法,記住便可。從上面的命令結果咱們也發現了一個很差的地方:行號和行不在一行。
[root@kaile~]
# sed '1,3=' person.txt
1
101,kaile,CEO
2
102,NB,CTO
3
103,Alex,COO
104,yy,
CFO
105,feixue,
CIO
命令說明:只打印1,2,3行的行號,同時打印輸出文件中的內容
[root@kaile~]
# sed '/yy/=' person.txt
101,kaile,CEO
102,NB,CTO
103,Alex,COO
4
104,yy,
CFO
105,feixue,
CIO
命令說明:
只打印正則匹配行的行號,同時輸出文件中的內容
[root@kaile~]
# sed -n '/yy/=' person.txt
4
命令說明:只顯示行號但不顯示行的內容即取消默認輸出。
[root@kaile~]
# sed -n '$=' person.txt
5
命令說明:
「$」表明最後一行,所以顯示最後一行的行號,變相得出文件的總行數。
方法改進:
[root@kaile~]
# sed '=' person.txt | sed 'N;s#\n# #'
1101,kaile,CEO
2102,NB,CTO
3103,Alex,COO
4104,yy,
CFO
5105,feixue,
CIO
命令說明:前面sed獲取文件的行號有一個缺點,咱們這裏使用Sed命令N來補償這個缺點。Sed命令N讀取下一行數據並附加到模式空間。
[root@kaile~]
# sed -n '1p;3p;5p' person.txt
101,kaile,CEO
103,Alex,COO
105,feixue,CIO
[root@kaile~]
# sed -n '2,4p;=' person.txt
1
102,NB,CTO
2
103,Alex,COO
3
104,yy,CFO
4
5
命令說明:-n去掉默認輸出,2,4p,輸出2到4行內容,=輸出所有的行的行號
[root@kaile~]
# sed -n '2,4{p;=}' person.txt
102,NB,CTO
2
103,Alex,COO
3
104,yy,CFO
4
命令說明:
‘2,4{p;=}’表明統一輸出2,4行的行號和內容
命令說明:刪除包含「kaile」的行,就直接用正則匹配字符串kaile便可
模式空間(pattern space):是sed軟件從文本讀取一行文本而後存入的緩衝區(這個緩衝區是在內存中的),而後使用sed命令操做模式空間的內容。
保持空間(hold space):是sed軟件另一個緩衝區,用來存放臨時數據,也是在內存中,可是模式空間和保持空間的用途是不同的。Sed能夠交換保持空間和模式空間的數據,可是不能在保持空間上執行普通的sed命令,也就是說咱們能夠在保持空間存儲數據。
下載地址:wget http://sedsed.sourceforge.net/sedsed-1.0 -O /bin/sedsed
sedsed詳解:http://aurelio.net/projects/sedsed/
下載調試工具
[root@kaile /]# wgethttp://sedsed.sourceforge.net/sedsed-1.0 -O /bin/sedsed
--2017-04-08 01:28:35-- http://sedsed.sourceforge.net/sedsed-1.0
正在解析主機sedsed.sourceforge.net... 216.34.181.96
正在鏈接sedsed.sourceforge.net|216.34.181.96|:80... 已鏈接。
已發出 HTTP 請求,正在等待迴應... 301 Moved Permanently
位置:http://aurelio.net/sedsed/sedsed-1.0[跟隨至新的 URL]
--2017-04-08 01:28:38-- http://aurelio.net/sedsed/sedsed-1.0
正在解析主機aurelio.net... 208.113.154.67
正在鏈接aurelio.net|208.113.154.67|:80... 已鏈接。
已發出 HTTP 請求,正在等待迴應... 301 Moved Permanently
位置:http://aurelio.net/projects/sedsed/sedsed-1.0[跟隨至新的 URL]
--2017-04-08 01:28:39-- http://aurelio.net/projects/sedsed/sedsed-1.0
再次使用存在的到aurelio.net:80 的鏈接。
已發出 HTTP 請求,正在等待迴應... 200 OK
長度:51346 (50K)[text/plain]
正在保存至: 「/bin/sedsed」
100%[===================================================================================================================>]51,346 58.3K/s in 0.9s
2017-04-08 01:28:40 (58.3 KB/s) - 已保存 「/bin/sedsed」 [51346/51346])
#給它執行權限
[root@kaile /]# which sedsed
/bin/sedsed
[root@kaile /]# chmod +x/bin/sedsed
Usage: sedsed OPTION [-e sedscript] [-fsedscriptfile] [inputfile]
OPTIONS:
-f,--file add file contents to thecommands to be parsed
-e,--expression add the script to thecommands to be parsed
-n,--quiet suppress automaticprinting of pattern space
--silent alias to --quiet
-d, --debug debug thesed script 開啓調試工具
--hide hide some debug info (options: PATT,HOLD,COMM)
a |
追加,在指定行後添加一行或多行文本* |
c |
取代指定的行 替換指定行 sed '1c ceshi' test.txt |
d |
刪除指定的行* $最後一行 sed '1,5d' 刪除一到5行內容 sed '5,$' 刪除5到最後一行 |
D |
刪除模式空間的部份內容,直到遇到換行符\n結束操做,與多行模式相關 |
i |
插入,在指定行前添加一行或多行文本* |
n |
清空模式空間的內容並讀入下一行 |
N |
不清空模式空間,並讀取下一行數據並追加到模式空間* |
p |
打印模式空間內容,一般p會與選項-n一塊兒使用* |
P(大寫) |
打印模式空間的內容,直到遇到換行符\n結束操做 |
q |
退出Sed |
r |
從指定文件讀取數據 |
s |
取代,s#old#new#g==>這裏g是s命令的替代標誌,注意和g命令區分。s命令替換* |
w |
另存,把模式空間的內容保存到文件中 |
y |
根據對應位置轉換字符 |
[root@kaile /]# sedsed -d --hide=HOLD -n 'N;2,3p'person.txt
PATT:1$ PATT當前模式空間
COMM:N 執行的命令N不清空模式空間,並讀取下一行數據並追加到模式空間*
PATT:1\n2$
COMM:2,3 p 執行的命令:p 打印
1
2
PATT:1\n2$
PATT:3$
COMM:N
PATT:3\n4$
COMM:2,3 p
PATT:3\n4$
PATT:5$
COMM:N
在咱們學習CentOS6系統優化時,有一個優化點:更改ssh服務遠程登陸的配置。主要的操做是在ssh的配置文件/etc/ssh/sshd_config加入下面5行文本。(下面參數的具體含義見其餘課程。)
Port 52113
PermitRootLogin no
PermitEmptyPasswords no
UseDNS no
GSSAPIAuthentication no
固然咱們可使用vi/vim命令編輯這個文本,可是這樣就比較麻煩,如今想用一條命令增長5行文本到第13行前?
注意:修改前別忘了備份配置文件:cp /etc/ssh/sshd_config{,.bak}
上面的命令知識要是不懂請看通配符章節
這道企業面試題能夠用咱們學過的sed命令多行追加功能就能夠搞定。
第一步備份咱們的ssh 修改配置文件首先須要備份
[root@kaile ~]# cp /etc/ssh/ssh_config/etc/ssh/ssh_config.bak
cp:是否覆蓋"/etc/ssh/ssh_config.bak"? y
第二步利用所學sed知識來完成追加
命令
i插入,在指定行前添加一行或多行文本
a 追加,在指定行後添加一行或多行文本
#sed 插入到指定行前添加一行或多行文本
[root@kaile ~]#sed -i '13i Port 52113\nPermitRootLogin no\nPermitEmptyPasswords no\nUseDNSno\nGSSAPIAuthentication no' /etc/ssh/sshd_config
命令說明:題目要求在第13行前插入,那就須要使用命令13i。
#sed追加到指定行後添加一行或多行文本
[root@kaile ~]#sed -i '12a Port 52113\nPermitRootLogin no\nPermitEmptyPasswords no\nUseDNSno\nGSSAPIAuthentication no' /etc/ssh/sshd_config