2009年4月15日 星期三

linux指令 - sed

sed的這一個指令真的很好用,它可以用來對檔案進行分析,並且可以以行為單位進行刪除,取代,新增,插入,列印的動作,真的非常好用,跟awk一樣非常好用~
find, grep, awk, sed這四個均列為非常好用的程式。
先列出鳥哥的網頁的部分資料吧~

$ sed [-nefr] [動作]
參數:
-n  :使用安靜(silent)模式。在一般 sed 的用法中,所有來自 STDIN 
的資料一般都會被列出到螢幕上。但如果加上 -n 參數後,則只有經過
sed 特殊處理的那一行(或者動作)才會被列出來。
-e  :直接在指令列模式上進行 sed 的動作編輯;
-f  :直接將 sed 的動作寫在一個檔案內, -f filename 則可以執行 filename 內的 
sed 動作;
-r  :sed 的動作支援的是延伸型正規表示法的語法。(預設是基礎正規表示法語法)
-i  :直接修改讀取的檔案內容,而不是由螢幕輸出。

動作說明:  [n1[,n2]]function
n1, n2 :不見得會存在,一般代表『選擇進行動作的行數』,舉例來說,如果我的動作
是需要在 10 到 20 行之間進行的,則『 10,20[動作行為] 』

function 有底下這些咚咚:
a   :新增, a 的後面可以接字串,而這些字串會在新的一行出現(目前的下一行)~
c   :取代, c 的後面可以接字串,這些字串可以取代 n1,n2 之間的行!
d   :刪除,因為是刪除啊,所以 d 後面通常不接任何咚咚;
i   :插入, i 的後面可以接字串,而這些字串會在新的一行出現(目前的上一行);
p   :列印,亦即將某個選擇的資料印出。通常 p 會與參數 sed -n 一起運作~
s   :取代,可以直接進行取代的工作哩!通常這個 s 的動作可以搭配
正規表示法!例如 1,20s/old/new/g 就是啦!


目前剛好要用到,大量取代的功能~而且是多個資料夾內的大量資料,因此,就先拿一些小檔案來開刀啦~
案例1:
之前在寫Makefile時,除了clean與另一個我就是寫clean_target,但是,最近覺得還是寫distclean會比較好,那就用以下的指令啦~
$ find . -name Makefile -exec sed -i 's/clean_target/distclean/g' {} \;
噹噹,不到10秒就完成了二十個檔案以上的修改啦~

$ cat /etc/man.config | grep 'MAN'| sed 's/#.*$//g' | sed '/^$/d
以上這一個指令是把man.config的檔案內含有MAN的行取出,並且移除掉以#為開頭的註解,並且把一整行都是空白的部份刪掉,除了最後一個sed的指令是指把一整行都是空白的部分刪掉不懂之外,其它部分都懂哩!然後,用man查了一下sed發現原來有這一個語法,如下:
       /regexp/
Match lines matching the regular expression regexp.

所以
$ sed '/^$/d' file
是表示把在file檔案內的空白行刪除

[2009.11.24 補充]
在Windows下使用sed(安裝GnuWin32)時要注意的是,當我們在Linux下使用sed時,是使用'(單引號)當作分隔鍵,而在winodws下則必需要使用"(雙引號)當作分隔鍵;本文章以下的內容都是使用linux的表示方式,若要在windows下使用的話,請自動把單引號轉換為雙引號

以下是把當前目錄的所有文字檔內的內容含有Caspar-comment這一個字串的這一行全部刪掉
% sed -i '/.*Caspar-comment.*/d' *

[2009.12.07 補充]
上面的使用方式,也會掃到資料夾,所以,會出現錯誤訊息,這個時候呢?用find可以達到指針對檔案作動作
% find . -type f | grep -v svn | xargs -i sed -i '/.*Caspar-comment.*/d' {}

[2010.01.01 補充]
同時對多個檔案,加入多個取代的字串
例:把first.txt與second.txt內的內容,同時把a轉換為A且把b轉換為B
% sed -e 's/a/A/g' -e 's/b/B/g' first.txt second.txt

[2010.09.22 補充]
把目前資料夾(包含子目錄)下的所有檔案,每一行的檔案最後多餘的空白移除掉~
% find . -type f | grep -v svn | grep .c$ | xargs -i sed -i 's/ \+$//g' {}

[2010.12.16 補充]把test.txt檔案內符合ValueString這一個字串的整行刪掉,且不區分大小寫
% sed -i '/^ValueString$/Id' test.txt

[2010.12.19 補充]
在Windows下使用sed(GnuWin32)時,若有使用-i這一個參數,會多出一個sed開頭並且亂數結尾的備份檔案,目前還找不到方法可以不要產生這一個備份檔案。所以,只好用另一個方法達成。
sed -i '/^ValueString$/Id' test.txt>temp_test.txt
move /Y temp_test.txt test.txt

若直接使用以下的方法,會產生空白檔案!我也不知道為什麼會這樣!
sed -i '/^ValueString$/Id' test.txt>test.txt

[2010.12.28 補充]
刪除完美符合CPT_*的字串
sed.exe "/^CPT_\*$/Id" test.txt
目前已知的特殊字元
&, ^, $, *,

[2014.07.08 補充]
sed -i '$ a\插入字符串' datafile

參考資料:
鳥哥的Linux私房菜
linux sed命令技巧
正規表示式的入門與應用(二)

沒有留言: