sed工具簡介
用法:
sed [-nefri] 動作
參數:
-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就是
范例:
范例一:將 /etc/passwd 的內容列出,并且我需要打印行號,同時,請將第 2~5 行刪除!
[root@linux ~]# nl /etc/passwd |sed '2,5d'
1 root:x:0:0:root:/root:/bin/bash
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
.....(后面省略).....
看到了吧?因為 2-5 行給他刪除了,所以顯示的數據中,就沒有 2-5 行啰~
另外,注意一下,原本應該是要下達 sed -e 才對,沒有 -e 也行啦!
同時也要注意的是, sed 后面接的動作,請務必以 '' 兩個單引號括住喔!
而,如果只要刪除第 2 行,可以使用 nl /etc/passwd | sed '2d' 來達成,
至于第 3 到最后一行,則是 nl /etc/passwd | sed '3,$d' 的啦!
范例二:承上題,在第二行后(亦即是加在第三行)加上『drink tea?』字樣!
[root@linux ~]# nl /etc/passwd |sed '2a drink tea'
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
function有以下這些參數:
a:新增,a后面可以接字符串,而這些字符串會在新的一行出現(目前的下一行)
c:替換,c后面可以接字符串,這些字符串可以替換n1,n2之間的行
d:刪除,因為是刪除,所以d后面通常不接任何參數
i:插入,i的后面可以接字符串,而這些字符串會在新的一行出現(目前的上一行)
p:打印,也就是將某個選擇的數據打印出來,通常p會與參數sed -n 一起運行
s:替換,可以直接進行替換的工作,通常這個s的動作可以搭配正則表達式,例如1,20s/old/new/g就是
范例:
>>范例一:將 /etc/passwd 的內容列出,并且我需要打印行號,同時,請將第 2~5 行刪除!
[root@linux ~]# nl /etc/passwd |sed '2,5d'
1 root:x:0:0:root:/root:/bin/bash
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
.....(后面省略).....
看到了吧?因為 2-5 行給他刪除了,所以顯示的數據中,就沒有 2-5 行啰~
另外,注意一下,原本應該是要下達 sed -e 才對,沒有 -e 也行啦!
同時也要注意的是, sed 后面接的動作,請務必以 '' 兩個單引號括住喔!
而,如果只要刪除第 2 行,可以使用 nl /etc/passwd | sed '2d' 來達成,
至于第 3 到最后一行,則是 nl /etc/passwd | sed '3,$d' 的啦!
>>范例二:承上題,在第二行后(亦即是加在第三行)加上『drink tea?』字樣!
[root@linux ~]# nl /etc/passwd |sed '2a drink tea'
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
drink tea
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
嘿嘿!在 a 后面加上的字符串就已將出現在第二行后面啰!那如果是要在第二行前呢?
nl /etc/passwd | sed '2i drink tea' 就對啦!
范例三:在第二行后面加入兩行字,例如『Drink tea or .....』『drink beer?』
[root@linux ~]# nl /etc/passwd | sed '2a Drink tea or ......
drink beer ?'
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
Drink tea or ......
drink beer ?
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
這個范例的重點是,我們可以新增不只一行喔!可以新增好幾行~
但是每一行之間都必須要以反斜線 \ 來進行新行的增加喔!所以,上面的例子中,
我們可以發現在第一行的最后面就有 \ 存在啦!那是一定要的喔!
范例四:我想將第2-5行的內容取代成為『No 2-5 number』呢?
[root@linux ~]# nl /etc/passwd | sed '2,5c No 2-5 number'
1 root:x:0:0:root:/root:/bin/bash
No 2-5 number
6 sync:x:5:0:sync:/sbin:/bin/sync
沒有了 2-5 行,嘿嘿嘿嘿!我們要的數據就出現啦!
范例五:僅列出第 5-7 行
[root@linux ~]# nl /etc/passwd | sed -n '5,7p'
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
為什么要加 -n 的參數呢?您可以自行下達 sed '5,7p' 就知道了!(5-7行會重復輸出)
有沒有加上 -n 的參數時,輸出的數據可是差很多的喔!
范例六:我們可以使用 ifconfig 來列出 IP ,若僅要 eth0 的 IP 時?
[root@linux ~]# ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:51:FD:52:9A:CA
inet addr:192.168.1.12 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::250:fcff:fe22:9acb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
....(以下省略).....
其實,我們要的只是那個 inet addr:..那一行而已,所以啰,利用 grep 與 sed 來捉
[root@linux ~]# ifconfig eth0 | grep 'inet ' | sed 's/^.addr://g' |
sed 's/Bcast.$//g'
您可以將每個管線 (|) 的過程都分開來執行,就會曉得原因啰!
去頭去尾之后,就會得到我們所需要的 IP 亦即是 192.168.1.12 啰~
>> 范例七:將 /etc/man.config 檔案的內容中,有 MAN 的設定就取出來,但不要說明內容。
[root@linux ~]# cat /etc/man.config | grep 'MAN'| sed 's/#.*$//g' | \
> sed '/^$/d'
每一行當中,若有 # 表示該行為批注,但是要注意的是,有時候,
批注并不是寫在第一個字符,亦即是寫在某個指令后方,如底下的模樣:
『shutdown -h now # 這個是關機的指令』,批注 # 就在指令的后方了。
因此,我們才會使用到將 #.*$ 這個正規表示法!
>> 范例八:利用 sed 直接在 ~/.bashrc 最后一行加入『# This is a test』
[root@linux ~]# sed -i '$a # This is a test' ~/.bashrc
上頭的 -i 參數可以讓你的 sed 直接去修改后面接的檔案內容喔!而不是由屏幕輸出。
至于那個 $a 則代表最后一行才新增的意思
awk工具
用法:awk '條件類型1{動作1} 條件類型2{動作2} ...' filename
awk主要是處理每一行的字段內的數據,而默認的字段的分隔符為空格符或[Tab]鍵
在每一行的每個字段都是有變量名稱的,那就是$1,$2等變量名稱
$0代表的是一整行數據的意思
整個awk的處理流程是:
1.讀入第一行,并將第一行的數據填入$0,$1,$2等變量
2.依據條件類型的限制,判斷是否需要進行后面的動作
3.做完所有的動作與條件類型
4.若還有后續的"行"的數據,則重復上面的1~3的步驟,直到所有的數據都讀完為止
awk是以行為一次處理的單位,而以字段為最小的處理單位
>變量名稱 代表意義
NF 每一行($0)擁有的字段總數
NR 目前awk所處理的是"第幾行"數據
FS 目前的分隔符,默認是空格符
awk的命令形式:
awk [-F|-f|-v] 'BEGIN{} //{command1;command2} END{}' file
[-F|-f|-v]:大參數,-F用于指定分隔符,-f調用腳本,-v定義變量var=value
' ':引用代碼塊
BEGIN:初始化代碼塊,在對每一行進行處理之前,初始化代碼,主要是引用全局變量,設置FS分隔符
//:匹配代碼塊,可以是字符串或者是正則表達式
{}:命令代碼塊,包含一條或多條命令
;:多條命令使用分號分割
END:結尾代碼塊,在對每一行進行處理之后再執行的代碼塊,主要是進行最終計算或輸出結尾摘要信息
特殊要點:
$0:表示當前行
$1:表示每一行的第一個字段
FNR:與NR類似,不過多文件記錄不遞增,每個文件都從1開始
FS:BEGIN時定義的分隔符
RS:記錄的分隔符,默認為換行符(即文本是按一行一行來讀取的)
+:匹配時表示1個或1個以上
/[0-9][0-9]+/:兩個或兩個以上數字
/[0-9][0-9]*/:一個或一個以上數字
OFS:輸出字段分隔符,默認是空格,也可以是制表符等
ORS:輸出的記錄分隔符,默認為換行符,即處理結果也是按一行一行輸出屏幕的
范例
print & $0
print 是awk打印指定內容的主要命令
awk '{print}' /etc/passwd == awk '{print $0}' /etc/passwd
awk '{print " "}' /etc/passwd //不輸出passwd的內容,而是輸出相同個數的空行,進一步解釋了awk是一行一行處理文本
awk '{print "a"}' /etc/passwd //輸出相同個數的a行,一行只有一個a字母
awk -F":" '{print $1}' /etc/passwd
awk -F: '{print $1; print $2}' /etc/passwd //將每一行的前二個字段,分行輸出,進一步理解一行一行處理文本
awk -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd //輸出字段1,3,6,以制表符作為分隔符
-f指定腳本文件
awk -f script.awk file
BEGIN{
FS=":"
}
{print $1} //效果與awk -F":" '{print $1}'相同,只是分隔符使用FS在代碼自身中指定
awk 'BEGIN{X=0} /^$/{ X+=1 } END{print "I find",X,"blank lines."}' test
I find 4 blank lines.
ls -l|awk 'BEGIN{sum=0} !/^d/{sum+=$5} END{print "total size is",sum}'
//計算文件大小
total size is 17487
-F指定分隔符
$1 指指定分隔符后,第一個字段,$3第三個字段, \t是制表符
一個或多個連續的空格或制表符看做一個定界符,即多個空格看做一個空格
awk -F":" '{print $1}' /etc/passwd
awk -F":" '{print $1 $3}' /etc/passwd //$1與$3相連輸出,不分隔
awk -F":" '{print $1,$3}' /etc/passwd //多了一個逗號,$1與$3使用空格分隔
awk -F":" '{print $1 " " $3}' /etc/passwd //$1與$3之間手動添加空格分隔
awk -F":" '{print "Username:" $1 "\t\t Uid:" $3 }' /etc/passwd //自定義輸出
awk -F: '{print NF}' /etc/passwd //顯示每行有多少字段
awk -F: '{print $NF}' /etc/passwd //將每行第NF個字段的值打印出來
awk -F: 'NF==4 {print }' /etc/passwd //顯示只有4個字段的行
awk -F: 'NF>2{print $0}' /etc/passwd //顯示每行字段數量大于2的行
awk '{print NR,$0}' /etc/passwd //輸出每行的行號
awk -F: '{print NR,NF,$NF,"\t",$0}' /etc/passwd //依次打印行號,字段數,最后字段值,制表符,每行內容
awk -F: 'NR==5{print}' /etc/passwd //顯示第5行
awk -F: 'NR==5 || NR==6{print}' /etc/passwd //顯示第5行和第6行
route -n|awk 'NR!=1{print}' //不顯示第一行
//匹配代碼塊
//純字符匹配 !//純字符不匹配 ~//字段值匹配 !~//字段值不匹配 ~/a1|a2/字段值匹配a1或a2
awk '/mysql/' /etc/passwd
awk '/mysql/{print }' /etc/passwd
awk '/mysql/{print $0}' /etc/passwd //三條指令結果一樣
awk '!/mysql/{print $0}' /etc/passwd //輸出不匹配mysql的行
awk '/mysql|mail/{print}' /etc/passwd
awk '!/mysql|mail/{print}' /etc/passwd
awk -F: '/mail/,/mysql/{print}' /etc/passwd //區間匹配
awk '/[2][7][7]*/{print $0}' /etc/passwd //匹配包含27為數字開頭的行,如27,277,2777...
awk -F: '$1~/mail/{print $1}' /etc/passwd //$1匹配指定內容才顯示
awk -F: '{if($1~/mail/) print $1}' /etc/passwd //與上面相同
awk -F: '$1!~/mail/{print $1}' /etc/passwd //不匹配
awk -F: '$1!~/mail|mysql/{print $1}' /etc/passwd