標籤:指令碼 Regex sed awk
【著作權聲明:轉載請保留出處:blog.csdn.net/gentleliu。Mail:shallnew at 163 dot com】
sed和awk類似,是很重要的文本過濾工具。
調用sed和調用awk一樣,有三種方式:
1. 在命令列鍵入命令;
2.將sed命令插入指令檔,然後調用sed;
3. 將sed命令插入指令檔,並使sed指令碼可執行。
使用sed命令列格式為:
sed [option] ‘sed cmd’ inputfile
使用sed指令檔,格式為:
sed [option] -f sed_script_file.sed inputfile
無論何種方式,如果sed沒有指定輸入檔案,sed從標準輸入中接受輸入,一般是鍵盤或重新導向結果。使用sed無論命令是什麼,sed並不與初始設定檔案打交道,它操作的只是一個拷貝,然後所有的改動如果沒有重新導向到一個檔案,將輸出到螢幕。
sed選項如下:
-e進行多項編輯,即對輸入行應用多條sed命令時使用
-n取消預設的輸出
-f指定sed指令碼的檔案名稱
Sed有如下命令:
p 列印匹配行
= 顯示檔案行號
a \ 在定位行號後附加新文本資訊
i \ 在定位行號後插入新文本資訊
d 刪除定位行
c \ 用新文本替換定位文本
s 使用替換模式替換相應模式
r 從另一個檔案中讀文本
w 寫文本到一個檔案
q 第一個模式比對完成後推出或立即推出
l 顯示與八進位 A S C I I代碼等價的控制字元
{ } 在定位行執行的命令組
n 從另一個檔案中讀文本下一行,並附加在下一行
g 將模式2粘貼到/pattern n/
y 傳送字元
n 延續到下一輸入行;允許跨行的模式比對語句
下面來講一下sed的各種命令。本系列關於sed的樣本使用以下文字檔:
#cat passwdroot:x:0:0:root:/root:/bin/shproxy:x:13:13:proxy:/bin:/bin/shoperator:x:37:37:Operator:/var:/bin/shftp:x:83:83:ftp:/home/ftp:/bin/shnobody:x:99:99:nobody:/home:/bin/shsshd:x:103:99:Operator:/var:/bin/sh#
1. p命令
1) 使用P命令列印檔案內容。
#sed 'p' passwdroot:x:0:0:root:/root:/bin/shroot:x:0:0:root:/root:/bin/shproxy:x:13:13:proxy:/bin:/bin/shproxy:x:13:13:proxy:/bin:/bin/shoperator:x:37:37:Operator:/var:/bin/shoperator:x:37:37:Operator:/var:/bin/shftp:x:83:83:ftp:/home/ftp:/bin/shftp:x:83:83:ftp:/home/ftp:/bin/shnobody:x:99:99:nobody:/home:/bin/shnobody:x:99:99:nobody:/home:/bin/shsshd:x:103:99:Operator:/var:/bin/shsshd:x:103:99:Operator:/var:/bin/sh#
發現每一行列印了兩次,我們使用-n選項關閉預設的輸出:
#sed -n 'p' passwdroot:x:0:0:root:/root:/bin/shproxy:x:13:13:proxy:/bin:/bin/shoperator:x:37:37:Operator:/var:/bin/shftp:x:83:83:ftp:/home/ftp:/bin/shnobody:x:99:99:nobody:/home:/bin/shsshd:x:103:99:Operator:/var:/bin/sh
# awk實現對比:
#awk '{print}' passwdroot:x:0:0:root:/root:/bin/shproxy:x:13:13:proxy:/bin:/bin/shoperator:x:37:37:Operator:/var:/bin/shftp:x:83:83:ftp:/home/ftp:/bin/shnobody:x:99:99:nobody:/home:/bin/shsshd:x:103:99:Operator:/var:/bin/sh#
使用sed不一定要列印所有行出來,我們可以定位到某一行對其進行操作,使用s e d在檔案中定位文本的方式:
x x為一行號,如 1
x,y 表示行號範圍從x到y,如2,5表示從第2行到第5行
/pattern/ 查詢包含模式的行。例如 / d i s k /或/[a-z]/
/pattern /pattern / 查詢包含兩個模式的行。例如 / d i s k / d i s k s /
pattern/ , x 在給定行號上查詢包含模式的行。如 / r i b b o n / , 3
x , /pattern/ 通過行號和模式查詢匹配行。 3 . / v d u /
x,y! 查詢不包含指定行號 x和y的行。1 , 2 !
2) 列印第3行:
#sed -n '3p' passwdoperator:x:37:37:Operator:/var:/bin/sh#
awk實現對比:
#awk '{if(NR==3)print}' passwdoperator:x:37:37:Operator:/var:/bin/sh#
3) 列印2到4行:
#sed -n '2,4p' passwdproxy:x:13:13:proxy:/bin:/bin/shoperator:x:37:37:Operator:/var:/bin/shftp:x:83:83:ftp:/home/ftp:/bin/sh#
awk實現對比:
#awk '{if(NR<=4 && NR>=2)print}' passwdproxy:x:13:13:proxy:/bin:/bin/shoperator:x:37:37:Operator:/var:/bin/shftp:x:83:83:ftp:/home/ftp:/bin/sh#
4) 列印匹配行
#sed -n '/var/p' passwdoperator:x:37:37:Operator:/var:/bin/shsshd:x:103:99:Operator:/var:/bin/sh#
awk實現對比:
#awk '/var/{print}' passwdoperator:x:37:37:Operator:/var:/bin/shsshd:x:103:99:Operator:/var:/bin/sh#
5) 列印最後一行
#sed -n '$p' passwdsshd:x:103:99:Operator:/var:/bin/sh
2. “=”命令,列印行號
#sed -n '/var/=' passwd36
awk實現對比:
#awk '/var/{print NR}' passwd36
如果列印行號及匹配行,必須使用兩個sed命令,並使用 e選項。第一個命令列印模式比對行,第二個使用 =選項列印行號,格式為 sed -n -e /pattern/p -e /pattern/=。
#sed -n -e '/var/p' -e '/var/=' passwdoperator:x:37:37:Operator:/var:/bin/sh3sshd:x:103:99:Operator:/var:/bin/sh6#
#awk '/var/{print $0 "\n" NR}' passwdoperator:x:37:37:Operator:/var:/bin/sh3sshd:x:103:99:Operator:/var:/bin/sh6#
3. \a命令,在指定行後附加新文本
使用符號a \,可以將指定文本一行或多行附加到指定行後面。文本附加操作時,結果輸出在標準輸出上。要想在附加操作後編輯文本,必須儲存檔案,然後運行另一個 s e d 命令編輯它。這時檔案的內容又被移至緩衝區。
#sed '/root/a\this line is add by sed\haha' passwdroot:x:0:0:root:/root:/bin/shthis line is add by sedhahaproxy:x:13:13:proxy:/bin:/bin/shoperator:x:37:37:Operator:/var:/bin/shftp:x:83:83:ftp:/home/ftp:/bin/shnobody:x:99:99:nobody:/home:/bin/shsshd:x:103:99:Operator:/var:/bin/sh#
#awk '{print;if(/root/)print"this line is add by awk"}' passwdroot:x:0:0:root:/root:/bin/shthis line is add by awkproxy:x:13:13:proxy:/bin:/bin/shoperator:x:37:37:Operator:/var:/bin/shftp:x:83:83:ftp:/home/ftp:/bin/shnobody:x:99:99:nobody:/home:/bin/shsshd:x:103:99:Operator:/var:/bin/sh#
4. i\命令,和\a命令類似,只是插入文本在匹配行前一行
5. \c命令,修改指定行
#sed '/root/c\this line is modify by sed\h' passwdthis line is modify by sedhproxy:x:13:13:proxy:/bin:/bin/shoperator:x:37:37:Operator:/var:/bin/shftp:x:83:83:ftp:/home/ftp:/bin/shnobody:x:99:99:nobody:/home:/bin/shsshd:x:103:99:Operator:/var:/bin/sh
#awk '{if(/root/){print"this line is modify by awk"}else {print}}' passwdthis line is modify by awkproxy:x:13:13:proxy:/bin:/bin/shoperator:x:37:37:Operator:/var:/bin/shftp:x:83:83:ftp:/home/ftp:/bin/shnobody:x:99:99:nobody:/home:/bin/shsshd:x:103:99:Operator:/var:/bin/sh#
6. d命令,刪除匹配行
#sed '1,4d' passwdnobody:x:99:99:nobody:/home:/bin/shsshd:x:103:99:Operator:/var:/bin/sh#
#awk '{if(NR>4)print}' passwdnobody:x:99:99:nobody:/home:/bin/shsshd:x:103:99:Operator:/var:/bin/sh#
7. s命令,替換行文本
格式為:[address [,address]] s/ pattern-to-find /replacement-pattern/[g p w n]
該命令在指定行([address [,address]]),使用S命令,將符合模式pattern-to-find的文本替換為文本replacement-pattern,p選項將列印出替換的行,g選項替換全域所有出現模式,預設情況下只替換第一次出現模式。w 檔案名稱 使用此選項將輸出定向到一個檔案。
現在我們來替換檔案第1,2行的bin字串,替換為sedtest:
# sed '1,2s/bin/sedtest/' passwd root:x:0:0:root:/root:/sedtest/shproxy:x:13:13:proxy:/sedtest:/bin/shoperator:x:37:37:Operator:/var:/bin/shftp:x:83:83:ftp:/home/ftp:/bin/shnobody:x:99:99:nobody:/home:/bin/shsshd:x:103:99:Operator:/var:/bin/sh
我們可以使用sed的-n選項以及s命令的p選項來僅僅列印被替換的行:
# sed -n '1,2s/bin/sedtest/p' passwdroot:x:0:0:root:/root:/sedtest/shproxy:x:13:13:proxy:/sedtest:/bin/sh
使用s命令的g選項可以替換當前行所有符合模式的地方:
# sed -n '1,2s/bin/sedtest/pg' passwdroot:x:0:0:root:/root:/sedtest/shproxy:x:13:13:proxy:/sedtest:/sedtest/sh
該命令使用awk實現較複雜。
8. r命令,從另一個檔案中讀文本
從new.txt檔案讀取內容附加到檔案符合模式的指定行後面。
# sed '3r new.txt' passwdroot:x:0:0:root:/root:/bin/shproxy:x:13:13:proxy:/bin:/bin/shoperator:x:37:37:Operator:/var:/bin/shthis line from new.txtftp:x:83:83:ftp:/home/ftp:/bin/shnobody:x:99:99:nobody:/home:/bin/shsshd:x:103:99:Operator:/var:/bin/sh
此操作使用awk較複雜。
9. q命令,在符合模式行後面退出
# sed '/Operator/q' passwdroot:x:0:0:root:/root:/bin/shproxy:x:13:13:proxy:/bin:/bin/shoperator:x:37:37:Operator:/var:/bin/sh
# awk '{print;if (NR >= 3)exit}' passwdroot:x:0:0:root:/root:/bin/shproxy:x:13:13:proxy:/bin:/bin/shoperator:x:37:37:Operator:/var:/bin/sh
10. l命令,顯示檔案控制字元
對之前使用new.txt檔案稍作修改(加入一些控制字元)如下:
# cat new.txtthis line from new.txtkkh#
使用l命令顯示如下:
# sed -n 'l' new.txtthis line from new.txt\033[B$kkh$\r$#
Awk未發現有此功能。
11. sed使用Regex進複雜替換
刪除行首字母:
# sed 's/^[a-z]*//g' passwd
在匹配文本後面增加文本:
# sed 's/[0-9][0-9]:/&8902:/g' passwdroot:x:0:0:root:/root:/bin/shproxy:x:13:8902:13:8902:proxy:/bin:/bin/shoperator:x:37:8902:37:8902:Operator:/var:/bin/shftp:x:83:8902:83:8902:ftp:/home/ftp:/bin/shnobody:x:99:8902:99:8902:nobody:/home:/bin/shsshd:x:103:8902:99:8902:Operator:/var:/bin/sh
對password檔案做如下操作:
a. 刪除已:分隔的第一列
b. 將所有:替換為空白格
c. 刪除行尾sh
# sed 's/^[a-z]*://g' passwd | sed 's/:/ /g' | sed 's/sh$//g'x 0 0 root /root /bin/x 13 13 proxy /bin /bin/x 37 37 Operator /var /bin/x 83 83 ftp /home/ftp /bin/x 99 99 nobody /home /bin/x 103 99 Operator /var /bin/
刪除行首兩字元:
# echo "hello sed." | sed 's/^..//g'llo sed.
刪除行尾兩字元:
# echo "hello sed." | sed 's/..$//g'hello se
在sed字串後面添加字串” world”:
# echo "hello sed." | sed 's/sed/& world/g'hello sed world.
awk和sed的比較,我目前片面看來,sed更適合修改編輯檔案,尤其是要修改行中某一字串的時候很方便;而awk更適合用來取出每一行按指定分割符號分割出來的資訊。
awk更複雜,感覺更像一種程式設計語言一樣,而sed更像一個工具,用少量代碼可以輕鬆搞定一些處理。這兩工具各取所長,有的時候可以聯合使用,處理起文本來就更好了。
shell文本過濾編程(九):sed命令