linux命令學(xué)習(xí)(二)——sed

學(xué)習(xí)資料:《linux大棚命令百篇上》


什么是sed

sed是stream editor的縮寫,翻譯過來就是“流編輯器”思杯,而實(shí)際上它的作用也正如描述的那樣。sed命令是一個(gè)面向行處理的工具挠进, 以行為處理單位色乾,可以實(shí)現(xiàn)很強(qiáng)大的處理能力。sed對(duì)每一行進(jìn)行處理后輸出到標(biāo)準(zhǔn)輸出领突,反應(yīng)在我們可見的角度就是暖璧,sed會(huì)將修改的內(nèi)容輸出到shell上顯示出來,而不會(huì)對(duì)源文件做任何修改(當(dāng)然如果想對(duì)源文件進(jìn)行修改也是可以的)君旦。

像學(xué)習(xí)數(shù)學(xué)一樣澎办,sed的用法可以用一個(gè)公式概括:
sed [選項(xiàng)] command file
其中:

  • command:對(duì)文件每行(或者選定行)進(jìn)行的操作。
  • file:要操作的文件金砍。

sed的工作原理

sed在按行處理文件時(shí)局蚀,會(huì)將要處理的那行放入緩沖區(qū)中,然后sed命令會(huì)對(duì)緩沖區(qū)中的內(nèi)容進(jìn)行處理恕稠。處理完成后將緩沖區(qū)的內(nèi)容送入屏幕顯示琅绅,接著處理下一行,直到文件結(jié)束谱俭。所以整個(gè)處理過程中奉件,sed操作的都是緩沖區(qū)的內(nèi)容,因而并不會(huì)對(duì)源文件進(jìn)行任何修改昆著。

下面看一個(gè)小例子來展示一下sed的魅力:

首先用一個(gè)腳本來創(chuàng)建一個(gè)包含行號(hào)文件

#! /bin/bash
for i in {1..5}
do
    echo "hello linux $i" >> hello
done

運(yùn)行腳本后县貌,產(chǎn)生了一個(gè)hello文件,文件內(nèi)容如下:

wangsheng@ubuntu[18:47:21]:~/Documents$ sh file.sh
wangsheng@ubuntu[18:47:26]:~/Documents$ cat hello
hello linux 1
hello linux 2
hello linux 3
hello linux 4
hello linux 5

如果我只想看文件中的第2行凑懂,就可以用sed命令這么寫:

wangsheng@ubuntu[18:49:47]:~/Documents$ sed -n '2p' hello
hello linux 2

可以看到只顯示了hello文件中的第2行煤痕。這個(gè)例子很簡(jiǎn)單,只是展示一下sed的基本用法接谨,后面會(huì)對(duì)sed的用法進(jìn)行詳細(xì)描述摆碉。這里的-n是sed提供的一個(gè)選項(xiàng),而'2p'就是sed的command部分表示打印第二行脓豪;hello是file部分巷帝,表示操作的是hello這個(gè)文件。


sed的詳細(xì)用法

花樣的命令

命令是sed用法中command部分扫夜,sed之所以擁有強(qiáng)大的功能楞泼,就是因?yàn)槠鋍ommand部分可以組合成非常多的花樣。常用的command通常由兩部分構(gòu)成笤闯,一部分是范圍設(shè)定堕阔,也就是選定行;另一部分是動(dòng)作處理颗味,即對(duì)選定的行執(zhí)行什么樣的操作超陆。

范圍設(shè)定

范圍設(shè)定,顧名思義就是sed命令需要對(duì)哪一行或者哪幾行進(jìn)行操作浦马。值得注意的是时呀,如果不選定行,那么默認(rèn)對(duì)所有行執(zhí)行此操作捐韩。常用的范圍設(shè)定有如下幾種形式:

  • x:x為行號(hào)退唠,表示選定第x行
    #顯示第2行
    wangsheng@ubuntu[18:49:47]:~/Documents$ sed -n '2p' hello
    hello linux 2
    
  • x,y:從第x行到第y行
    #顯示2-4行
    wangsheng@ubuntu[19:40:50]:~/Documents$ sed -n '2,4p' hello
    hello linux 2
    hello linux 3
    hello linux 4
    
  • x,$:從第x行到最后一行
    #顯示第4行到最后一行
    wangsheng@ubuntu[19:44:41]:~/Documents$ sed -n '4,$p' hello
    hello linux 4
    hello linux 5
    
  • x,y!:不包含指定行號(hào)x到y(tǒng)的行
    #顯示除了第3行的所有行
    wangsheng@ubuntu[19:47:33]:~/Documents$ sed -n '3!p' hello
    hello linux 1
    hello linux 2
    hello linux 4
    hello linux 5
    
  • /pattern/:查詢包含該模式的行,這里的pattern可以使用正則表達(dá)式荤胁。
    #查詢顯示含有5的行
    wangsheng@ubuntu[19:47:40]:~/Documents$ sed -n '/5/p' hello
    hello linux 5
    #查詢顯示含有l(wèi)inux的行
    wangsheng@ubuntu[19:50:47]:~/Documents$ sed -n '/linux/p' hello
    hello linux 1
    hello linux 2
    hello linux 3
    hello linux 4
    hello linux 5
    
  • x,/pattern/ :通過行號(hào)和模式查詢匹配行瞧预,表示從第x行到匹配該模式的行。

動(dòng)作處理

動(dòng)作處理會(huì)提供很多豐富的動(dòng)作供我們選擇仅政,可以利用這些動(dòng)作對(duì)某行內(nèi)容進(jìn)行加入垢油、刪除、修改等操作圆丹。這里介紹幾個(gè)常用的動(dòng)作:

  • p : 打印滩愁,將選中的那行打印輸出到屏幕上。通常 p 會(huì)與參數(shù) sed -n 一起用辫封。(關(guān)于-n選項(xiàng)的作用硝枉,后面在介紹sed選項(xiàng)的時(shí)候會(huì)詳細(xì)說明)廉丽。

    #源文件
    wangsheng@ubuntu[20:04:00]:~/Documents$ cat hello
    hello linux 1
    hello java 2
    hello c++ 3
    hello android 4
    hello php 5
    #顯示第2行
    wangsheng@ubuntu[20:04:06]:~/Documents$ sed -n '2p' hello
    hello java 2
    #顯示最后一行
    wangsheng@ubuntu[20:05:38]:~/Documents$ sed -n '$p' hello
    hello php 5
    #顯示含有java的行
    wangsheng@ubuntu[20:16:25]:~/Documents$ sed -n '/java/p' hello
    hello java 2
    
  • a : 增加,a 的后面可以接字符串妻味,而這些字符串會(huì)在新的一行出現(xiàn)(目前的下一行)正压,而如果想添加多行,可以使用\n換行符责球。

    #在文件末添加一行hello python
    wangsheng@ubuntu[20:08:48]:~/Documents$ sed '$a hello python' hello
    hello linux 1
    hello java 2
    hello c++ 3
    hello android 4
    hello php 5
    hello python
    #使用\n可以添加換行焦履,例如本例在含有android行的下一行添加了兩行內(nèi)容
    wangsheng@ubuntu[20:17:39]:~/Documents$ sed '/android/a hello\nworld' hello
    hello linux 1
    hello java 2
    hello c++ 3
    hello android 4
    hello
    world
    hello php 5
    
  • c : 行替換,c 的后面可以接字符串雏逾,這些字符串可以替換 n1,n2 之間的行嘉裤。

    #第2行替換為hello world
    wangsheng@ubuntu[20:09:00]:~/Documents$ sed '2c hello world' hello
    hello linux 1
    hello world
    hello c++ 3
    hello android 4
    hello php 5
    #第3行至最后一行替換為hello world
    wangsheng@ubuntu[20:11:06]:~/Documents$ sed '3,$c hello world' hello
    hello linux 1
    hello java 2
    hello world
    
  • d : 刪除行,因?yàn)槭莿h除栖博,所以 d 后面通常不接任何內(nèi)容屑宠,表示刪除選定行的內(nèi)容。

    #刪除第1行
    wangsheng@ubuntu[20:12:58]:~/Documents$ sed '1d' hello
    hello java 2
    hello c++ 3
    hello android 4
    hello php 5
    #刪除含有java的行
    wangsheng@ubuntu[20:19:05]:~/Documents$ sed '/java/d' hello
    hello linux 1
    hello c++ 3
    hello android 4
    hello php 5
    
  • s : 替換笛匙,可以直接進(jìn)行搜尋替換的工作侨把。通常 s 可以搭配正則表達(dá)式。

    格式:sed 's/要替換的字符串/新的字符串/g' (要替換的字符串可以用正則表達(dá)式)

    #搜索含有java的行妹孙,并將該行的java替換成javaee
    wangsheng@ubuntu[20:19:49]:~/Documents$ sed '/java/s/java/javaee/g' hello
    hello linux 1
    hello javaee 2
    hello c++ 3
    hello android 4
    hello php 5
    #也可以使用該功能刪除某個(gè)字符串秋柄,例如本例將java替換成空即刪掉了第2行的java
    wangsheng@ubuntu[20:25:13]:~/Documents$ sed '/java/s/java//g' hello
    hello linux 1
    hello  2
    hello c++ 3
    hello android 4
    hello php 5
    

    有時(shí)候我們不想在當(dāng)前行的下一行或者上一行添加內(nèi)容,而希望在行首或行尾追加內(nèi)容時(shí)怎么辦呢蠢正?

    其實(shí)就可以使用s功能骇笔。其中^表示行首,$表示行尾

    #在每行行首添加head------
    wangsheng@ubuntu[20:29:56]:~/Documents$ sed 's/^/head------/g' hello
    head------hello linux 1
    head------hello java 2
    head------hello c++ 3
    head------hello android 4
    head------hello php 5
    #在每行行尾追加------tail
    wangsheng@ubuntu[20:35:12]:~/Documents$ sed 's/$/------tail/g' hello
    hello linux 1------tail
    hello java 2------tail
    hello c++ 3------tail
    hello android 4------tail
    hello php 5------tail
    #在第1行行尾追加------tail
    wangsheng@ubuntu[20:35:36]:~/Documents$ sed '1s/$/------tail/g' hello
    hello linux 1------tail
    hello java 2
    hello c++ 3
    hello android 4
    hello php 5
    

    另外嚣崭,如果說s是代表替換笨触,那么末尾的g是什么意思呢?

    其實(shí)字符g代表的意思是每行出現(xiàn)的字符全部替換雹舀,如果想在特定字符處添加芦劣,g就有用了,否則只會(huì)替換每行第一個(gè)说榆,而不繼續(xù)往后找了虚吟。

  • r : 文件插入,可以在當(dāng)前行的下一行插入指定文件中的內(nèi)容签财。

    #需要插入的文件內(nèi)容
    wangsheng@ubuntu[20:28:34]:~/Documents$ cat foo
    +++this is file in foo+++
    #使用a動(dòng)作插入時(shí)串慰,只會(huì)將foo當(dāng)做字符串插入
    wangsheng@ubuntu[20:27:46]:~/Documents$ sed '/java/a foo' hello
    hello linux 1
    hello java 2
    foo
    hello c++ 3
    hello android 4
    hello php 5
    #使用r命令插入時(shí),會(huì)將foo代表的文件內(nèi)容插入
    wangsheng@ubuntu[20:28:12]:~/Documents$ sed '/java/r foo' hello
    hello linux 1
    hello java 2
    +++this is file in foo+++
    hello c++ 3
    hello android 4
    hello php 5
    

好用的選項(xiàng)

剛才我們已經(jīng)提到了sed的命令的基本構(gòu)成唱蒸,下面來看看sed有哪些好玩的選項(xiàng)邦鲫。

  • -n:使用安靜(silent)模式。在一般 sed 的用法中神汹,所有來自 STDIN的內(nèi)容一般都會(huì)被輸出到屏幕上庆捺。但如果加上 -n 參數(shù)后古今,則只有經(jīng)過sed 特殊處理的那一行(或者動(dòng)作)才會(huì)被輸出出來。

    #使用-n選項(xiàng)滔以,只會(huì)輸出處理的那一行
    wangsheng@ubuntu[20:43:59]:~/Documents$ sed -n '/java/a ======' hello
    ======
    #不使用-n選項(xiàng)沧卢,輸出所有行
    wangsheng@ubuntu[20:44:22]:~/Documents$ sed '/java/a ======' hello
    hello linux 1
    hello java 2
    ======
    hello c++ 3
    hello android 4
    hello php 5
    
  • -e:如果我要執(zhí)行的動(dòng)作包含兩個(gè)或以上怎么辦呢?這也很簡(jiǎn)單醉者,sed的-e屬性就是支持這個(gè)功能的,只要在每個(gè)動(dòng)作之前分別加上-e選項(xiàng)即可披诗。

    #前一個(gè)command輸出1-2行撬即,后一個(gè)command輸出第4行
    #每個(gè)command之前均加上-e選項(xiàng)就可以同時(shí)處理兩個(gè)動(dòng)作了
    wangsheng@ubuntu[20:44:33]:~/Documents$ sed -n -e '1,2p' -e '4p' hello
    hello linux 1
    hello java 2
    hello android 4
    
  • -f:如果設(shè)定的command部分太長(zhǎng),那么可以將command部分內(nèi)容寫到一個(gè)單獨(dú)的文件中呈队,然后使用-f選項(xiàng)來指定這個(gè)文件作為我們sed命令的command部分剥槐。

    #已經(jīng)寫好的command,存儲(chǔ)在文件中
    wangsheng@ubuntu[20:49:12]:~/Documents$ cat command
    /java/,/android/p
    #使用-f選項(xiàng)指定command文件
    wangsheng@ubuntu[20:49:16]:~/Documents$ sed -n -f command hello
    hello java 2
    hello c++ 3
    hello android 4
    
  • -i:直接修改讀取的文件內(nèi)容宪摧,而不是輸出到屏幕上粒竖。要注意此選項(xiàng)會(huì)直接改變?cè)次募膬?nèi)容,如果用此命令對(duì)系統(tǒng)配置文件修改的話几于,那么如果出現(xiàn)什么無法挽回的后果也只能怪自己作死了蕊苗。

    #源文件
    wangsheng@ubuntu[20:49:32]:~/Documents$ cat hello
    hello linux 1
    hello java 2
    hello c++ 3
    hello android 4
    hello php 5
    #第2行后添加新行,內(nèi)容為this is a new line
    wangsheng@ubuntu[20:52:32]:~/Documents$ sed -i '2a this is a new line' hello
    #源文件被修改
    wangsheng@ubuntu[20:53:20]:~/Documents$ cat hello
    hello linux 1
    hello java 2
    this is a new line
    hello c++ 3
    hello android 4
    hello php 5
    

sed實(shí)踐——自動(dòng)評(píng)分的腳本

學(xué)了知識(shí)當(dāng)然是為了用的沿彭,那么我們就用一個(gè)實(shí)際的例子來看看sed的應(yīng)用朽砰。

老師在服務(wù)器上為我們每個(gè)人創(chuàng)建了一個(gè)student_ids文件,里面有所有同學(xué)的名單喉刘,每個(gè)同學(xué)都要在該文件中為其他同學(xué)打分瞧柔。為了完成評(píng)分的工作,需要使用vi打開再一個(gè)個(gè)編輯睦裳,而且還不能全打滿分或者有規(guī)律地打分造锅,于是本著能偷懶就偷懶的原則,能不能寫一個(gè)自動(dòng)打分腳本呢廉邑?顯然哥蔚,使用sed這么強(qiáng)大的行處理功能實(shí)現(xiàn)起來肯定是沒問題的。

最終寫出來的腳本如下:

#!/bin/bash
count=0
#統(tǒng)計(jì)行數(shù)
while read line
do
    count=$(($count+1))
done < student_ids

for (( i=1; i<="$count"; i++ ))
do
    #產(chǎn)生84-99之間的隨機(jī)數(shù)
    let score=$RANDOM%15+84
    #第i行行尾追加隨機(jī)數(shù)
    sed -i "${i}s/$/ $score/g" student_ids
done

首先得到該文件的行數(shù)鬓催,并用一個(gè)變量count記錄下來肺素。然后循環(huán)count次,每次循環(huán)產(chǎn)生一個(gè)84-99之間的隨機(jī)數(shù)宇驾,使用sed命令將此隨機(jī)數(shù)插入到該行的行尾倍靡,然后下一次循環(huán)再對(duì)下一行執(zhí)行同樣的操作。值得注意的是课舍,這里sed使用了-i選項(xiàng)塌西,表示直接對(duì)源文件執(zhí)行此操作他挎,另外使用了強(qiáng)引用“”,而不是弱引用‘’捡需。如果是弱引用的話办桨,那么會(huì)將$score部分當(dāng)做是一個(gè)字符串,直接在每行行尾加上了$score這樣的字符串站辉;而如果使用強(qiáng)引用的話呢撞,則直接將$score代表的隨機(jī)數(shù)插入到行尾。

最后效果如下:

#student_ids源文件
wangsheng@ubuntu[21:03:12]:~/Documents$ cat student_ids
142006010124
142006010125
142006010126
142006010127
142006010128
142006010130
142006010121
142006010122
#執(zhí)行腳本
wangsheng@ubuntu[21:03:27]:~/Documents$ sh autograding.sh
8 lines completed!
#student_ids文件已經(jīng)被修改
wangsheng@ubuntu[21:03:32]:~/Documents$ cat student_ids
142006010124 98
142006010125 90
142006010126 94
142006010127 89
142006010128 96
142006010130 84
142006010121 94
142006010122 98
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末饰剥,一起剝皮案震驚了整個(gè)濱河市殊霞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌汰蓉,老刑警劉巖绷蹲,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異顾孽,居然都是意外死亡祝钢,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門若厚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拦英,“玉大人,你說我怎么就攤上這事测秸×湔拢” “怎么了?”我有些...
    開封第一講書人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵乞封,是天一觀的道長(zhǎng)做裙。 經(jīng)常有香客問我,道長(zhǎng)肃晚,這世上最難降的妖魔是什么锚贱? 我笑而不...
    開封第一講書人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮关串,結(jié)果婚禮上拧廊,老公的妹妹穿的比我還像新娘。我一直安慰自己晋修,他們只是感情好吧碾,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著墓卦,像睡著了一般倦春。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,096評(píng)論 1 291
  • 那天睁本,我揣著相機(jī)與錄音尿庐,去河邊找鬼。 笑死呢堰,一個(gè)胖子當(dāng)著我的面吹牛抄瑟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播枉疼,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼皮假,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了骂维?” 一聲冷哼從身側(cè)響起钞翔,我...
    開封第一講書人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎席舍,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哮笆,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡来颤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了稠肘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片福铅。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖项阴,靈堂內(nèi)的尸體忽然破棺而出滑黔,到底是詐尸還是另有隱情,我是刑警寧澤环揽,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布略荡,位于F島的核電站,受9級(jí)特大地震影響歉胶,放射性物質(zhì)發(fā)生泄漏汛兜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一通今、第九天 我趴在偏房一處隱蔽的房頂上張望粥谬。 院中可真熱鬧,春花似錦辫塌、人聲如沸漏策。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掺喻。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間巢寡,已是汗流浹背喉脖。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抑月,地道東北人树叽。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像谦絮,于是被迫代替她去往敵國(guó)和親题诵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,871評(píng)論 25 707
  • 學(xué)習(xí)資料:《linux大棚命令百篇上》 awk介紹及簡(jiǎn)單實(shí)用 以下是在網(wǎng)上找到的兩個(gè)awk的介紹: awk是一種處...
    陌上疏影涼閱讀 711評(píng)論 0 3
  • 本文筆記源自這里——[實(shí)驗(yàn)樓]歡迎大家在下面交流其中有問題的地方喜歡請(qǐng)點(diǎn)收藏层皱,每日更新(全部已親自實(shí)踐). 一. ...
    東皇Amrzs閱讀 3,977評(píng)論 7 54
  • 玩家進(jìn)行游戲性锭,僅僅是因?yàn)橄胪瓿梢豢钣螒蛎矗窟€是希望通過游戲達(dá)到什么目的叫胖?接下來草冈,我們簡(jiǎn)單討論一下這個(gè)問題。 游戲作...
    清寒如秋閱讀 1,092評(píng)論 0 0
  • 苦戀三部曲(組詩) ? 夕陽瘦 一. 求婚 新月般纖柔 流水無波的輕盈 你帶來風(fēng)的律動(dòng) 指尖上絮語 你把四季雕刻成...
    水畔細(xì)語閱讀 669評(píng)論 2 2