Linux“文本三劍客”之sed

“文本三劍客”中,grep是文本過濾器,而sed是基于行的文本流編輯器。
sed是將文件中的文本逐行讀取到內存中進行處理。

  1. sed工作原理
  2. sed命令
    2.1 OPTION
    2.2 SCRIPT
  3. sed使用示例

1 sed工作原理

sed有兩個工作空間,Pattern space(模式空間)和Hold space(保持空間)。


image.png

Pattern space 模式空間

sed會把文件內容的每一行復制一份出來放到自己的Pattern space中,在其中處理以后,處理的結果送到stdout(標準輸出):

  1. 默認情況sed會處理每一行,但我們可以讓sed處理只被模式(如正則表達式)匹配到的文本。
  2. Pattern space中被用戶給出的模式匹配到的內容,則edit(編輯)后再送到stdout。
  3. 如果不能匹配,則不做任何編輯操作,直接輸出到stdout。

Hold space 保持空間

Hold space用于在使用高級編輯功能時,實現與Pattern space空間中的內容進行追加、覆蓋、互換等操作。后邊高級編輯示例中會詳細解釋。

2 sed命令

sed - stream editor for filtering and transforming text
sed [OPTION]... 'SCRIPT' [input-file]...
sed命令需要將命令選項OPTION和處理腳本SCRIPT結合使用,來對文本進行特定的處理動作。

2.1 OPTION

  • -n:不輸出模式空間的內容至屏幕stdout
    [默認情況下,會將不被pattern匹配到的內容直接輸出到stdout,-n則不輸出這部分內容]
  • -e script,--expression=script:多點編輯;
    默認只支持一個script(被pattern匹配到的內容將被執行的編輯命令),加-e可以指定多個script。
    如:sed -e 's@^#[[:space:]]*@@' -e '/^UUID/d' /etc/fstab
  • -f /PATH/TO/SED_SCRIPT_FILE
    SED_SCRIPT_FILE中,每行都有一個script,從文件中逐行讀取script,省去-e的繁瑣
  • -r,--regexp-extended:支持擴展正則表達式
  • -i[SUFFIX],--in-place[=SUFFIX]:直接編輯原文件(有風險,用之前先做備份)(sed默認不直接編輯原文件)。

2.2 SCRIPT

SCRIPT由"地址定界"和"編輯命令"兩部分組成,和vi編輯器的末行模式命令相似。兩部分中間無空格。

地址定界的語法格式
  1. 地址定界為空,表示全文;
  2. 單地址:
    N:指定一個行號,表示第N行;
    /PATTERN/:給出一個模式,表示被模式匹配到的每一行。
  3. 地址范圍:
    M,N:表示從第M行到第N行;
    M,+N:表示從第M行開始,到往后N行之間的所有行(包含第M行);
    M,/PATTERN/:表示從第M行到被PATTERN匹配到的第一行之間的所有行
    /PATTERN1/,/PATTERN2/:表示從被PATTERN1匹配到的第一行,到被PATTERN2匹配到的第一行之間的所有行。
  4. 用“~”表示步進:
    如:1~2表示所有奇數行,2~2表示所有偶數行。
編輯命令
  1. d:delete pattern space,刪除模式匹配到的內容(模式空間中的內容)
    d是一個特殊的操作
  2. p:print the current pattern space:打印模式匹配到的內容(模式空間中的內容)
    p也是一個特殊的操作,會將pattern匹配到的內容顯示兩遍,如果不加選項,顯示結果為,模式空間中的全部內容+被pattern匹配到的內容;
    如果只想顯示被pattern匹配的內容,配合使用-n選項,將不顯示默認輸出的模式空間全部內容。
  3. a \text:append,在模式匹配到的行后面追加文本“text”,支持使用\n(換行符號)實現多行追加(注意文本前用\轉義)
  4. i:insert,在模式匹配到的行前面插入文本“text”,支持使用\n(換行符號)實現多行插入(注意文本前用\轉義)
    比如,在fstab文件中所有以UUID開頭的行前面加入注釋:
    sed '/^UUID/i # Add device based on UUID.' fstab
  5. c \text:把匹配到的行替換為"text"(注意是整行替換!!);
  6. w /PATH/TO/SOMEFILE:保存模式匹配到的行至指定的文件中;
    例如:將fstab中所有以非#開頭的行保存到當前目錄下的fstab.new文件中:
    sed '/[#]/w fstab.new' fstab
  7. r /PATH/FROM/SOMEFILE:讀取指定文件的內容至當前文件被模式匹配到的行后面;
    例如:將/etc/issue文件中的內容顯示到fstab文件第3行的后面:
    sed '3r /etc/issue' fstab
  8. =:為模式匹配到的行打印行號(在行的前面另起一個新行來打印行號);
    例如:將fstab中所有以UUID開頭的行都打印行號:
    sed '/^UUID/=' fstab
  9. !:條件取反(!放在地址定界和編輯命令之間)
    地址定界!編輯命令
    例如:前邊有個例子,“將fstab中所有以非#開頭的行保存到當前目錄下的fstab.new文件中”
    我們使用 “sed '/[#]/w fstab.new' fstab”;
    在這里可以這樣“ sed '/^#/!w fstab.new' fstab”,它表示所有#號開頭的行都不寫入fstab.new文件,即非#開頭的行就寫入。
  10. s///:查找替換,其分隔符可自行指定,常用的有s@@@,s###等;
    替換標記:
    g:全局替換
    w /PATH/TO/SOMEFILE:將替換成功的結果保存至指定文件中;
    p:顯示替換成功的行;
高級編輯命令

高級編輯命令用于Pattern space和Hold space中內容的追加、覆蓋和互換,有以下幾個:

  1. Pttern space --> Hold space
    h:把模式空間中的內容覆蓋至 > 保持空間(hold space)中;
    H:把模式空間中的內容追加至 >> 保持空間(hold space)中;
  2. Hold space --> Pattern space
    g:把保持空間中的內容覆蓋至 > 模式空間中;
    G:把保持空間中的內容追加至 >> 模式空間中;
  3. 模式匹配的下一行 --> Pattern space
    n:覆蓋讀取匹配到的行的下一行至 > 模式空間中
    N:追加讀取匹配到的行的下一行至 >> 模式空間中
  4. Pattern space <--> Hold space
    x:把模式空間中的內容與保持空間中的內容互換;
  5. 刪除Pattern sapce中的行
    d:刪除模式空間中的行
    D:刪除多行模式空間中的所有行(多行模式空間比如,N命令追加到模式空間中行)

3 sed使用示例

普通編輯命令示例

sed是否用得好,主要是看SCRIPT的編寫能力。

  1. 刪除/etc/grub2.cfg文件中所有以空白字符開頭的行的行首的所有空白字符:
    sed 's@^[[:space:]]\+@@' /etc/grub2.cfg
  2. 刪除/etc/fstab文件中所有以#開頭的行的行首的#號及#后邊的所有空白字符:
    sed 's@^#[[:space:]]*@@' /etc/fstab
  3. 輸出一個絕對路徑給sed命令,要求取出其目錄名,類似dirname命令執行結果:
    echo "/var/log/messages" | sed 's@[^/]\+/\?$@@'
    或使用-r選項支持擴展正則表達式:
    echo "/var/log/messages" | sed -r 's@[^/]+/?$@@'

高級編輯命令示例與命令解析

要使用sed的高級編輯命令,需要對sed的工作流程非常熟悉。

  • sed -n 'n;p' FILE
    顯示偶數行(;分號用來分隔多個命令)
    命令解析:
    因為是n;p,沒有地址定界,表示逐行讀取所有內容。
    1、首先讀取第1行到pattern space,遇到第一個命令是n,覆蓋讀取下一行(也就是第2行)到pattern space,所以現在pattern space中的內容變為第2行(第1行被覆蓋掉);
    2、然后是p命令,將pattern space中的第2行顯示出來;
    3、接著讀取第3行到pattern space,同上,顯示第4行;
    4、以此類推,顯示所有偶數行。

注意:如果沒有-n選項,則將顯示全部內容,并且偶數行顯示兩遍。

  • sed '1!G;h;$!d' FILE
    逆序顯示文件內容,相當于tac
    命令解析:
    1、讀取第1行到pattern space,先碰到“1!G”命令,表示第1行不做G操作;
    2、然后碰到下一個命令“h”,表示將pattern space中的內容覆蓋至hold space,就是將第1行內容復制到了hold space中;
    3、接下來碰到“$!d”命令,表示將pattern space中不是最后一行的內容全部刪除,pattern space中當前還有第1行的內容,則將其刪除。第1行的讀取到此結束。
    4、接著讀取第2行,“1!G”命令將hold space中的內容(第1行的內容)覆蓋至pattern space,所以目前pattern space中的內容變為“第2行+第1行”;
    5、然后碰到“h”命令,將pattern space中的內容(第2行+第1行)復制到hold space中(hold space中原來的第1行內容被覆蓋掉),所以現在hold space中的內容為“第2行+第1行”;
    6、下一個命令“$!d”,同上,將pattern space中的“第2行+第1行”內容刪除。
    第2行的讀取到此結束。
    7、以此類推,知道讀取第n-1行結束時,hold space的內容為“第n-1行+第n-2行....第2行+第1行”,pattern space為空;
    8、最后讀取第n行,“1!G”命令將hold space內容追加到pattern space,則pattern space內容變為“第n行...第1行”;
    9、“h”命令將pattern space的內容覆蓋復制到hold space,則現在hold space的內容為“第n行...第1行”;
    10、最后碰到“$!d”命令,因為是最后一行,則不刪除pattern space的內容,所以pattern space中的內容還是“第n行...第1行”。
    11、讀取完全部內容后,默認輸出pattern space中的全部內容,即“第n行...第1行”,將原內容逆序顯示!

  • sed '$!d' FILE
    取出最后一行,相當于tail -1
    命令解析:
    1、讀取第1行到pattern space,pattern中的命令為“$!d”(不是最后一行,則刪除),所以把第1行從pattern space中刪了
    2、依次類推,一直刪到倒數第2行;
    3、到最后一行,不刪了,保留在pattern space中,然后輸出到stdout。

  • 其他幾個高級編輯命令示例
    sed '$!N;$!D' FILE:顯示最后兩行,相當于tail -2
    sed '/^$/d;G' FILE:刪除原有所有空白行,再為所有非空白行后添加一個空白行
    sed 'n;d' FILE:顯示奇數行;
    sed 'G' FILE:在原有的每行后方添加一個空白行;

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,316評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,481評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,241評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,939評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,697評論 6 409
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,182評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,247評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,406評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,933評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,772評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,973評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,516評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,638評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,866評論 1 285
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,644評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,953評論 2 373

推薦閱讀更多精彩內容

  • Sed工具工作原理及特性 1. sed是流編輯器,每一次讀取一行到內存中,即稱之為模式空間(pattern spa...
    魏鎮坪閱讀 10,997評論 0 12
  • 本文承接之前寫的三十分鐘學會AWK一文,在學習完AWK之后,趁熱打鐵又學習了一下SED,不得不說這兩個工具真的堪稱...
    mylxsw閱讀 4,411評論 3 74
  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經改了很多 但是錯誤還是無法避免 以后資料會慢慢更新 大...
    數據革命閱讀 12,197評論 2 33
  • sed篇總共分成6章:(簡書版) Sed&awk筆記之sed篇:簡單介紹 Sed&awk筆記之sed篇:模式空間與...
    magic5650閱讀 640評論 0 3
  • 時間不曾為我等待,生活沒有那么簡單。 我的喘息沒有誰能聽見,因為我出身平凡,所以要飛到更高,也許外面的世界沒有想象...
    冰鎮夏天閱讀 240評論 0 6