Linux 文本修正工具sed的使用

何爲sed

sed是Stream Editor的簡稱,是Linux自帶的一個文本處理工具,以行爲單位,對文本進行處理,可以對每行的內容做替換、刪除、新增、選取等操作。

sed在處理文本時,會把當前行讀入到緩衝區,這個緩衝區稱爲模版塊(Pattern Space),然後用相關命令處理模板塊的內容,處理完成後,將緩衝區的內容輸出,直到文件末尾。此外sed也提供了臨時緩衝區(Hold Space),用於實現更加複雜的文本操作。

sed命令行格式爲:

sed [option]... {script-only-if-no-other-script} [input-file]...

option爲選項,後面接命令,再後面接輸入文件。

命令

sed單個命令的語法爲:

[n1[,n2]]<function>

n1n2可選,代表選擇進行function操作的前置條件,n1n2有多種取值方式:

  • 當取值爲數字或$時,代表行號的限定範圍,$表示最後一行,例如:
    從第10行開始,進行function操作,直到第20行,那麼可以寫爲:10,20<function>
    從第10行開始,進行function操作,可以寫爲:10<function>10,$<function>
    從第1行開始,進行function操作,直到第10行,可以寫爲:1,10
  • 當取值爲正則表達式時,代表行需要滿足正則表達式纔會進行function的相關操作,例如:
    從第10行開始,對不以Hello開頭的行進行function操作,可以寫爲10,/^Hello/<function>
  • 當取值爲包含!時,表示在一定條件下不執行相關操作,例如:
    不對第1到4行的文本執行function操作,可以寫爲:1,5!<function>

此外sed可以接受多個命令,可以用;隔開,或者用多個-e選項即可,在處理模版塊時會按照先後依次順序執行。

在介紹function之前,爲了方便演示,可以新建一個文件testfile,並寫入以下內容:

Line 1
Line 2
...
Line 10

或者使用Shell自動生成:

echo > testfile
for i in {1..10}
do
	echo "Line $i" >> testfile
done
基本function的種類:
  • a:在當前行下面插入文本。
    後面可以接字符串,這個字符串會插入到當前行的下一行,例如在第8行後插入字符串helloworld

    sed '8ahelloworld' testfile
    

    或者從第8行開始,在每行後面插入一個helloworld

    sed '8,$a helloworld'
  • i:在當前行上面插入文本
    類似於a,後面接字符串,這個字符串會插入到當前行的上一行,例如在第8行之前插入字符串helloworld

    sed '8ihelloworld' testfile
    
  • c:把當前的行替換爲新的文本
    例如把第八行的Line 8替換爲helloworld

    sed '8chelloworld' testfile
    
  • d:刪除當前的行
    例如刪除第八行的文本Line 8刪除:

    sed '8d' testfile
    

    或者刪除第5到第8行文本:

    sed '5,8d' testfile
    

    刪除包含字符串Line 8的行:

    sed '/Line 8/d' testfile
    
  • s:替換指定的字符串,語法規則如下:

    sed 's/Regexp/Replacement/Flags' file
    

    s命令將符合正則表達式Regexp的行全部替換成Replacement,最後的字符Flags爲標誌選項,有以下幾種:

    1. g:用Replacement替換模版空間中所有匹配Regexp的部分,則不僅僅是第一個匹配部分
      例如要將testfile中的單詞Line全部替換成Word,那麼可以寫作:
      sed 's/Line/Word/g' testfile
      
    2. 1到9的數字N:只用Replacement替換模版空間中,忽略第0N - 1個匹配Regexp的部分,然後將匹配Regexp的部分輸出。
      例如,下面案例會將Line替換爲Lixx
      sed 's/[a-z]/x/2g' testfile
      
    3. p:若發生了替換操作,則輸出模版空間中修改後的行數據,和p命令很類似
    4. w file-path:若發生了替換操作,將模板塊中的數據寫入到文件file-path
      例如下面示例會將從第5行開始,替換LineWord,並將替換後的結果輸出到當前目錄的outputfile文件,直到文件末尾:
      sed -n '5,$s/Line/Word/gw outputfile' testfile
      
    5. i:與Regexp匹配時,不區分大小寫
      例如,下面命令可以將Line替換成Word
      sed 's/line/Word/ig' testfile
      

    此外,也可利用s在每行頭部或者尾部添加字符串,可以利用字符^表示行頭,字符$表示行尾
    比如在每行行頭添加單詞Hello

    sed 's/^/Hello/g' testfile
    

    在行尾添加單詞Hello

    sed 's/$/Hello/g' testfile
    

    當然s前面也可以加上行範圍

  • p:打印當前模板塊空間的所有內容(模板塊的定義前面已經提到),並追加到默認輸出之後
    例如在每行後面追加一個單詞number,並將修改前和修改後的結果打印出來(-n表示不打印默認輸出):

    sed -n 'p;s/$/number/g;p' testfile
    

    或者從第8行開始,將以Line開頭的行打印出來

    sed '5,/Line/p' testfile
    
其他function種類:
  • n:讀取下一個輸入行,用下一個命令處理新的行而不是使用第一個命令

  • N:追加下一個輸入行到模板塊的後面並在中間嵌入一個新行,可以利用該命令將多個行的內容整合爲一行。
    例如下列命令可以將三行語句整合爲一行:

    sed 'N;N;s/\n/ /g' testfile 
    

    邏輯就是就是讀取三行後,然後將換行符\n替換爲空格。
    或者可以輸出行號爲奇數的行:

    sed -n '$!N;P' testfile
    
  • P:打印當前模板塊空間的第一行

模板塊和臨時緩衝區(Hold Space)的操作:

  • h:拷貝模板塊的內容到臨時緩衝區
  • H:追加模板塊的內容到臨時緩衝區
  • D:刪除模板塊的第一行(意味着這個被刪除的部分不會傳至標準輸出),並放棄之後的命令,然後對新讀入的內容,重頭執行sed
  • g:取得臨時緩衝區的內容,並替換當前模板塊中的文本
  • G:取得臨時緩衝區的內容,並追加到當前模板塊中文本的後面

可以利用sed的臨時緩衝區執行更加複雜的文本修改操作,舉一個經典的例子:

實現倒序輸出,即從最後一行開始逐行輸出到第一行
思路:要實現倒序輸出,我們需要在讀取每一行的時候,就將行的內容放在模板塊的前面。所以在讀第一行的時候,需要將第一行的文本從模式塊讀到臨時緩衝區,然後再讀第二行的時候,把臨時緩衝區中第一行的數據追加到模版塊,依次類推。只需要對第一行和最後一行的做特殊處理即可。

	sed '1!G;h;$!d' testfile

1!G表示不對第一行做G操作,$!d表示不對最後一行做d操作
執行過程示例圖:
在這裏插入圖片描述

其他操作:

  • I:列出不能打印字符的清單
  • q:退出sed

選項

option參數主要包含以下幾個:

  • -n--quiet--silent:僅顯示被sed特殊處理的行,如果不加,那麼所有來自輸入文本的數據都會被輸出,不論有沒有進行過修改。
  • -e <script>--expression=<script>:使用script,也可以省略掉-e
  • -f <script-file>--file=script-file:指定存放script的文件
  • -i[suffix]--in-place[=suffix]:如果不加suffix,那麼直接修改文件的內容,不輸出到終端。如果加了suffix,則會在處理前,對文件進行備份(複製),備份文件名會在原先文件名後面加上suffix,然後再對原文件進行修改
  • -l <number>--line-length=<number>
  • --posix:禁用的GNU擴展功能,例如replacement選項中中的\L\l\U\u\E
  • -r--regexp-extended:讓sed支持擴展的正則表達式
  • -s--separate:在處理多個文件時,對它們依次單獨處理,而不是視爲一個整體
  • -u--unbuffered:從輸入文件中加載儘可能少的行,並更頻繁地刷新輸出緩衝區,適合機器內存比較緊張的情況
  • -z--null-data:每行按照\0分隔,而不是換行符。
  • --help:查看sed幫助
  • --version:查看sed版本
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章