Linux正則與文字處理工具(10)
正則表示式 (Regular Expression, RE, 或稱為常規表示式)是通過一些特殊字元的排列,用於『查詢/替換/刪除』一行或多行文字或字串,簡單的說,正則表示式就是用在字串的處理上面的一種『表示公式』,正則表示式並不是一個工具程式,而是一個對字串處理的標準依據,如果您想要以正則表示式的方式處理字串,就得要使用支援正則表示式的工具程式才行,這類的工具程式很多,例如 vi,vim,sed,awk,gawk,egrep等.
正則表示式,對於系統管理員來說是非常重要的,因為系統會產生很多的資訊,這些資訊有的重要有的僅是警告,此時管理員可以通過正則表示式來過濾出相應的我們需要的欄位,你最好掌握這門技術,會對將來的資料分析,主機管理起到很大的幫助.
基礎正則表示式
在上一章說過正則表示式和萬用字元的區別,(正則表示式用來在檔案中匹配符合條件的字串,而萬用字元則是用來匹配符合條件的檔名)嗎? 其實這種區別只在Shell當中適用,因為用來在檔案當中搜尋字串的命令,如 grep、awk、sed 等命令可以支援正則表示式,而在系統當中搜尋檔案的命令,如 ls、find、cp 這些命令不支援正則表示式,所以只能使用shell自己的萬用字元來進行匹配了.
首先我們先來學習一下基礎的正則表示式吧,下面是我們常用的正則語法,我會給每一個語法,舉一個小例子,下面我們開始學習吧.
例項1: 使用 *
實現匹配前一個字元出現0次或任意多次(本例中,則是匹配g字元出現0次或任意多次)
[[email protected] ~]# ls
wang wangg wanggg
[[email protected] ~]# ls | grep "wang*"
wang
wangg
wanggg
[[email protected] ~]# ls | grep "wan*g*"
wang
wangg
wanggg
例項2: 使用 .
實現匹配除換行符以外的任意一個字元,(只匹配一個字元),一般我們把它叫做貪婪匹配
[[email protected] ~]# ls
wang wangg wanggg wangr
[[email protected] ~]# ls | grep "wang"
wang
[[email protected] ~]# ls | grep "wang."
wangg
wangr
[[email protected] ~]# ls | grep "wang.."
wanggg
例項3: 使用 ^
實現匹配行首是指定字元的行
[[email protected] ~]# ls
alert lyshark tcpl wakaka wang wangg wanggg woxin
[[email protected] ~]# ls | grep "^ly"
lyshark
[[email protected] ~]# ls | grep "^wa"
wakaka
wang
wangg
wanggg
[[email protected] ~]# ls | grep "^a"
alert
例項4: 使用 $
實現匹配行尾是指定字元的行
[[email protected] ~]# ls
alert lyshark tcpl wakaka wang wangg wanggg woxin
[[email protected] ~]# ls | grep "a$"
wakaka
[[email protected] ~]# ls | grep "ark$"
lyshark
[[email protected] ~]# ls | grep "^w" | grep "n$" #匹配開頭是w結尾是n的
woxin
例項5: 使用 []
實現匹配中括號內任意一個字元,(只匹配其中一個)
[[email protected] ~]# ls
ale1t ale2t ale3t aleat alebt alert
[[email protected] ~]# ls | grep "ale[a-z]t"
aleat
alebt
alert
[[email protected] ~]# ls | grep "ale[0-9]t"
ale1t
ale2t
ale3t
[[email protected] ~]# ls | grep "ale[ab]t"
aleat
alebt
例項6: 使用 [^]
實現匹配除了中括號字元以外的任意一個字元(^取反的意思)
[[email protected] ~]# ls
ale1t ale2t ale3t aleat aleAt aleBB alebt aleCT aleEt alert
[[email protected] ~]# ls | grep "ale[^0-9]t"
aleat
aleAt
alebt
aleEt
alert
[[email protected] ~]# ls | grep "ale[^A-Z]t"
ale1t
ale2t
ale3t
aleat
alebt
alert
[[email protected] ~]# ls | grep "ale[^AE]t"
ale1t
ale2t
ale3t
aleat
alebt
alert
例項7: 使用 ^[^]
實現匹配行首是與不是指定字元的行
[[email protected] ~]# ls
ale1t ale2t lyshark tcpl wakaka wang wangg wanggg woxin
[[email protected] ~]# ls | grep ^[a] #匹配行首是a開頭的
ale1t
ale2t
[[email protected] ~]# ls | grep ^[^a] #匹配行首不是a開頭的
lyshark
tcpl
wakaka
wang
wangg
wanggg
woxin
例項8: 使用 \{n}\
實現匹配前面的字元恰好出現了n次的行
[[email protected] ~]# ls
12333 13466614578 13562653874 172.168.1.2 18264758942 192.168.1.1 45666 78999
[[email protected] ~]# ls | grep "123\{3\}"
12333
[[email protected] ~]# ls | grep "[0-9][0-9][0-9]\{3\}" #匹配前兩個字元是0-9的,最後一個字元出現過3次的
12333
45666
78999
[[email protected] ~]# ls | grep "[1][3-8][0-9]\{9\}" #匹配手機號規則
13466614578
13562653874
18264758942
例項9: \{n,}\
實現匹配前面的字元的出現,不小於n次的行
[[email protected] ~]# ls
12333 123333 1233333
[[email protected] ~]# ls | grep "123\{3,\}" #前一個字元3的出現不小於3次
12333
123333
1233333
[[email protected] ~]# ls | grep "123\{4,\}" #前一個字元3的出現不小於4次
123333
1233333
例項10: \{n,m}\
實現匹配前面的字元出現,不小於n次,最多出現m次的行
[[email protected] ~]# ls
123 1233 12333 123333 1233333 12333333 123333333 1233333333 12333333333
[[email protected] ~]# ls |grep "123\{3,5\}" #前一個字元3最少出現3次,最多不大於5次
12333
123333
1233333
總結:匹配一個合法IP地址
[[email protected] ~]# ls
10.10.10.22 127.9.0.8 172.168.1.2 192.168.1.1 192.168.1.3 255.255.255.255
127.0.0.1 172.168.1.1 172.168.1.3 192.168.1.2 192.199.256.256 256.256.256.256
[[email protected] ~]# ls | egrep "^(([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|
2[0-4][0-9]|25[0-4])$"
10.10.10.22
172.168.1.1
172.168.1.2
172.168.1.3
192.168.1.1
192.168.1.2
192.168.1.3
總結:匹配一個合法郵箱地址
[[email protected] ~]# ls
[email protected] [email protected] [email protected] [email protected] [email protected]
[[email protected] ~]# ls | egrep "^[0-9a-zA-Z][0-9a-zA-Z_]{1,16}[0-9a-zA-Z]\@[0-9a-zA-Z-]*([0-9a-zA-Z])?\.(com|com.cn|net|
org|cn)$"
[email protected]
[email protected]
[email protected]
[email protected]
擴充套件正則表示式
事實上,一般使用者只要瞭解基礎型的正則語句就已經相當足夠了,不過,在某些時候,為了簡化命令的長度,還是需要擴充套件正則的支援的,打個比方,我們可以使用 cat xxx.log | grep -v '^$' |grep -v '^#'
來實現過濾文字中的註釋行,和空白行,但是這不夠精簡,它的執行還是會用到兩次的過濾,如果使用擴充套件正則表示式,我們可以這樣寫,cat xxx.log |egrep -v '^$|^#'
這樣一個命令就可實現上面的效果啦,此處我們需要說明的是,grep -E 和egrep效果是相同的,使用哪一個都一個樣.
熟悉了基礎正規表示式之後,再來看這個擴充套件正則表示式,是不是很輕鬆啊,親,下面我們就來分別說明這幾個符號的使用規則吧.
例項1: +
實現匹配前一個字元出現1次或任意多次
[[email protected] ~]# ls
gogle google gooogle gooogooogle goooogle gooooogle goooooogle
[[email protected] ~]# ls | grep -E "go+gle"
gogle
google
gooogle
goooogle
gooooogle
goooooogle
例項2: ?
實現匹配前一個字元出現0次,或1次
[[email protected] ~]# ls
gogle google gooogle gooogooogle goooogle gooooogle goooooogle
[[email protected] ~]# ls | grep -E "go?gle"
gogle
[[email protected] ~]# ls | grep -E "goo?gle"
gogle
google
例項3: |
實現匹配兩個或多個分支選擇
[[email protected] ~]# ls
alert lyshark rui wang
[[email protected] ~]# ls | grep -E "alert|lyshark"
alert
lyshark
[[email protected] ~]# ls | grep -E "wang|rui|alert"
alert
rui
wang
例項4: ()
實現將字元作為一個整體匹配,即模式單元
[[email protected] ~]# ls
dog dogdog dogdogdog hello_lyshark hello_world
[[email protected] ~]# ls | grep -E "(dog)+"
dog
dogdog
dogdogdog
[[email protected] ~]# ls | grep -E "hello_(world|lyshark)"
hello_lyshark
hello_world
Grep 行處理工具
grep (global search regular expression(RE) and print out the line 全面搜尋正則表示式並把行打印出來)是一種強大的文字搜尋工具,它能使用正則表示式搜尋文字,並把匹配的行打印出來,好了廢話不多說,先看命令格式.
[[email protected] ~]# grep --help
命令語法:[ grep [選項] [過濾選單] 檔名 ]
-a #將二進位制資料一同列出
-c #計算找到查詢字串的次數
-i #忽略大小寫差異
-n #順便標號顯示
-v #反選引數
-q #不顯示任何提示資訊,安靜模式
-E #使用擴充套件正則,egrep
-A #匹配指定字元的後n個字元
-B #匹配指定字元的前n個字元
-C #匹配指定字元的前n個和後n個字元
例項1: 使用 grep -n
引數過濾資料時,一同標號
[[email protected] ~]# cat /etc/passwd | grep -n "root"
1:root:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/root:/sbin/nologin
例項2: 使用 grep -v
反選列印,行中不包括/bin/bash的行
[[email protected] ~]# cat /etc/passwd | grep -vn "/bin/bash"
2:bin:x:1:1:bin:/bin:/sbin/nologin
3:daemon:x:2:2:daemon:/sbin:/sbin/nologin
4:adm:x:3:4:adm:/var/adm:/sbin/nologin
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
8:halt:x:7:0:halt:/sbin:/sbin/halt
....省略....
例項3: 使用 grep -i
過濾出不論大小寫的lyshark單詞的行
[[email protected] ~]# cat lyshark.log
LyShark
lyshark
admin
Admin
ADMIN
Good
GOOD
[[email protected] ~]# cat lyshark.log | grep -ni "lyshark"
1:LyShark
2:lyshark
例項4: 使用正則,過濾出開頭是 ^L
的行的內容
[[email protected] ~]# cat lyshark.log
LyShark
lyshark
admin
Admin
ADMIN
Good
GOOD
[[email protected] ~]# cat lyshark.log | grep -n "^L"
1:LyShark
例項5: 使用正則,過濾出開頭不是 ^L
的行的內容
[[email protected] ~]# cat lyshark.log
LyShark
lyshark
admin
Admin
ADMIN
Good
GOOD
[[email protected] ~]# cat lyshark.log | grep -n "[^L]yshark"
2:lyshark
例項6: 使用正則,過濾出開頭是小寫字母的行
[[email protected] ~]# cat lyshark.log
LyShark
lyshark
admin
Admin
ADMIN
Good
GOOD
123123
1233
66431
124adb
[[email protected] ~]# cat lyshark.log | grep -n "^[a-z]"
2:lyshark
3:admin
例項7: 使用正則,過濾出開頭不是,a-z或A-Z的行
[[email protected] ~]# cat lyshark.log
LyShark
lyshark
admin
Admin
ADMIN
Good
GOOD
123123
1233
66431
124adb
[[email protected] ~]# cat lyshark.log | grep -n "^[^a-zA-Z]"
8:123123
9:1233
10:66431
11:124adb
例項8: 使用正則,找出結尾是小數點的哪一行
[[email protected] ~]# cat lyshark.log
LyShark
lyshark
admin
Admin
ADMIN
Good
123123
1233.
66431.
[[email protected] ~]# cat lyshark.log |grep -n "\.$"
8:1233.
9:66431.
例項9: 使用正則,過濾掉開頭是#號的,和開頭是空行的行
[[email protected] ~]# cat lyshark.log
#LyShark
#lyshark
#admin
#Admin
ADMIN
Good
123123
1233.
66431.
[[email protected] ~]# cat lyshark.log | grep -v "^#" | grep -v "^$"
ADMIN
Good
123123
1233.
66431.
例項10: 使用正則,過濾出前一個字元o剛好出現兩次的行
[[email protected] ~]# cat lyshark.log
#LyShark
#lyshark
#admin
#Admin
ADMIN
Good
123123
1233.
66431.
[[email protected] ~]# cat lyshark.log |grep -n "o\{2\}"
7:Good
例項11: 使用正則,匹配開頭是0-9且結尾是點的行
[[email protected] ~]# cat lyshark.log
#LyShark
#lyshark
#admin
#Admin
ADMIN
Good
123123
1233.
66431.
[[email protected] ~]# cat lyshark.log |grep -n -E "^[0-9]+\."
9:1233.
10:66431.
例項12: 使用正則,匹配指定字元的後2個字元,或前2個字元
[[email protected] ~]# cat lyshark.log
lyshark
LySHARK
wang
rui
hello
world
alert
123123
45678
[[email protected] ~]# cat lyshark.log |grep -n -A 2 "hello"
5:hello
6-world
7-alert
[[email protected] ~]# cat lyshark.log |grep -n -B 2 "hello"
3-wang
4-rui
5:hello
Cut 列提取工具
cut命令用來顯示行中的指定部分,刪除檔案中指定欄位,cut經常用來顯示檔案的內容,類似於type命令.該命令有兩項功能,其一是用來顯示檔案的內容,它依次讀取由引數file所指明的檔案,將它們的內容輸出到標準輸出上.其二是連線兩個或多個檔案,如cut fl f2 > f3 將把檔案fl和f2的內容合併,然後通過輸出重定向符">" 的作用,將它們放入檔案f3中.
首先我們來看一下它的格式吧,如下:
[[email protected] ~]# cut --help
命令語法:[ cut [選項] [列號] 檔名 ]
-f #-f 列號:指定提取第幾列
-d #-d 分隔符:按照指定分隔符進行分割
-c #-c 字元範圍:不依賴分割符來分割,而是通過字元範圍進行欄位提取
-m #表示從第一個字元提取到第m個
-b #僅顯示行中指定直接範圍的內容
-n #與"-b"選項連用,不分割多位元組字元
n- #表示從第n個字元開始提取到結尾
n-m #表示從第n提取到第m個字元
--complement #補齊被選擇的位元組,字元或欄位
--out-delimiter=<欄位分隔符> #指定輸出內容是的欄位分割符
手動建立一個文字,新增內容列之間用tab分隔,用來測試後續內容
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
例項1: 通過使用 -f
選項指定過濾的列,並顯示到螢幕
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
[[email protected] ~]# cut -f 2 lyshark.log
NAME
WR
LC
LY
[[email protected] ~]# cut -f 2,5 lyshark.log
NAME Mark
WR 100
LC 90
LY 88
例項2: 通過使用 --complement
選項提取指定欄位之外的列,(列印除了第2列之外的列)
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
[[email protected] ~]# cut -f 2 --complement lyshark.log
ID AGE Gender Mark
1 22 m 100
2 26 m 90
3 23 m 88
例項3: 通過使用 -c
選項過濾/etc/passwd,並列印第1個到第3個字元
[[email protected] ~]# cut -c 1-3 /etc/passwd
roo
bin
dae
adm
lp:
syn
....省略....
例項4: 通過使用 -c -2
選項過濾/etc/passwd,並列印前2個字元
[[email protected] ~]# cut -c -2 /etc/passwd
ro
bi
da
ad
lp
....省略....
例項5: 通過使用 -c 5-
選項過濾/etc/passwd,列印從第5個字元開始到結尾
[[email protected] ~]# cut -c 5- /etc/passwd
:x:0:0:root:/root:/bin/bash
x:1:1:bin:/bin:/sbin/nologin
on:x:2:2:daemon:/sbin:/sbin/nologin
x:3:4:adm:/var/adm:/sbin/nologin
....省略....
例項6: 通過使用 -d
指定分隔符 -f
指定列印第個欄位,以下我們分別擷取第1和第7個欄位
[[email protected] ~]# cut -d ":" -f 1,7 /etc/passwd
root:/bin/bash
bin:/sbin/nologin
daemon:/sbin/nologin
adm:/sbin/nologin
lp:/sbin/nologin
sync:/bin/sync
....省略....
例項7: 通過使用 -c -3
指定擷取前3個字元,還可以通過 -c 3
擷取第3個字元
[[email protected] ~]# cut -c -3 /etc/passwd
roo
bin
dae
adm
lp:
....省略....
[[email protected] ~]# cut -c 3 /etc/passwd
o
n
e
m
:
n
....省略....
Sed 流編輯器
sed是一種流編輯器,它是文字處理中非常中的工具,能夠完美的配合正則表示式使用,功能不同凡響.處理時,把當前處理的行儲存在臨時緩衝區中,稱為 "模式空間" (pattern space),接著用sed命令處理緩衝區中的內容,處理完成後,把緩衝區的內容送往螢幕,接著處理下一行,這樣不斷重複,直到檔案末尾.檔案內容並沒有改變,除非你使用重定向儲存輸出.Sed主要用來自動編輯一個或多個檔案,簡化對檔案的反覆操作,編寫轉換程式等.
sed主要是來進行資料選取,替換,刪除,新增的命令,二話不說先看一下它的引數吧.
[[email protected] ~]# sed --help
命令語法:[ sed [選項] [範圍] [動作] 檔名 ]
-n #把經過sed命令處理的行輸出到螢幕
-e #允許對輸入資料應用多條sed命令編輯
-f #從sed指令碼中讀入sed操作,和awk命令的-f類似
-r #在sed中支援擴充套件正則表示式
-i #用sed的修改結果,寫到檔案
命令動作:
p #列印,輸出指定的行
a #追加,在當前行後新增一行或多行
i #插入,在當前行前插入一行或多行
c #整行替換,用c後面的字串替換原資料行
d #刪除,刪除指定的行
s #字串替換,格式:"行範圍s/舊字串/新字串/g"
#對sed命令我們要知道的是,它所有的修改都不會直接修改檔案的內容,而是在記憶體中進行處理然後列印到螢幕上
#如果想要寫入檔案,請使用 sed -i 選項才會儲存到文字中.
在進行實驗之前,首先建立一個檔案,來做測試用
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
例項1: 使用 sed '2p'
重複列印第二行資料
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# sed '2p' lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
1 WR 22 m 100 ←本行是2p列印的
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# sed '3p' lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
2 LC 26 m 90 ←本行是2p列印的
3 LY 23 m 88
4 XDL 40 b 100
例項2: 使用 sed -n
限定,只選取指定的行進行顯示
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# sed -n '2p' lyshark.log ←只打印第2行資料
1 WR 22 m 100
[[email protected] ~]# sed -n '1p' lyshark.log ←只打印第1行資料
ID NAME AGE Gender Mark
例項3: 使用 sed '2,4d'
刪除掉檔案2-4行,並顯示到螢幕,(原檔案內容並沒有被修改)
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# sed '2,4d' lyshark.log ←刪除2-4行的資料並列印
ID NAME AGE Gender Mark
4 XDL 40 b 100
[[email protected] ~]# sed '1d' lyshark.log ←刪除第1行的資料
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
例項4: 使用 sed '2[a|i]'
追加,或者插入資料指定資料
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# sed '2a hello lyshark' lyshark.log ←在第2行後面追加資料
ID NAME AGE Gender Mark
1 WR 22 m 100
hello lyshark
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# sed '2i hello lyshark' lyshark.log ←在第2行前面插入資料
ID NAME AGE Gender Mark
hello lyshark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
例項5: 使用 \
換行符,一次插入多行資料
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# sed '2a hello \ ←在第二行下面,插入一段話,用\隔開
> my name is lyshark \
> age 22 \
> boy ' lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
hello
my name is lyshark
age 22
boy
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
例項6: 使用 sed 'c'
實現整行替換資料
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# cat lyshark.log | sed '5c 5 WRS 99 m 111' ←整行替換第5行內容
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
5 WRS 99 m 111
例項7: 使用 sed
後面跟上 -i
選項,將第5行的修改,儲存進檔案,(-i選項是回寫)
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# sed -i '5c 5 WRS 99 m 111' lyshark.log
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
5 WRS 99 m 111 ←這裡的資料已經寫入成功
例項8: 字串的替換 sed 's/舊文字/新文字/g'
進行整行替換
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
5 WRS 99 m 111
[[email protected] ~]# sed '2s/WR/LyShark/g' lyshark.log ←將第2行的,WR替換成LyShark
ID NAME AGE Gender Mark
1 LyShark 22 m 100
2 LC 26 m 90
3 LY 23 m 88
5 WRS 99 m 111
[[email protected] ~]# sed '3s/LC/Admin/g' lyshark.log ←將第3行的,LC替換成Admin
ID NAME AGE Gender Mark
1 WR 22 m 100
2 Admin 26 m 90
3 LY 23 m 88
5 WRS 99 m 111
#注意:上方只是替換列印,並沒有儲存,如若想儲存請加 -i 屬性
例項9: 將第3行資料的開頭新增#註釋
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
5 WRS 99 m 111
[[email protected] ~]# sed '3s/^/#/g' lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
#2 LC 26 m 90
3 LY 23 m 88
5 WRS 99 m 111
例項10: 將第4和第5行的內容替換成空
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
5 WRS 99 m 111
[[email protected] ~]# sed -e '4s/LY//g ; 5s/WRS//g' lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 23 m 88
5 99 m 111
#sed 要進行多行操作時,只能通過 -e 寫多條操作語句,用 ; 或回車分隔
過濾IP地址小實驗
[[email protected] ~]# ifconfig
ens32: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.1.10 netmask 255.255.255.0 broadcast 192.168.1.255
inet6 fe80::897c:d72d:cd95:b9ec prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:b1:b7:be txqueuelen 1000 (Ethernet)
RX packets 2344 bytes 156370 (152.7 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 454 bytes 50049 (48.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[[email protected] ~]# ifconfig | grep "inet 192" |sed 's/^.*inet //g'
192.168.1.10 netmask 255.255.255.0 broadcast 192.168.1.255
[[email protected] ~]# ifconfig |grep "inet 192" |sed 's/^.*inet //g' |sed 's/ netmask.*$//g'
192.168.1.10
Printf 文字格式化
[[email protected] ~]# printf --help
輸出型別:
%ns: #輸出字串,n是數字,指代輸出幾個字元
%ni: #輸出證書,n是數字,指代輸出幾個數字
%m.nf: #輸出浮點數,m和n是數字,指代輸出整數位和小數位
輸出格式:
\a: #輸出警告音
\b: #輸出退格鍵,也就是Backspace鍵
\f: #清屏
\n: #換行符
\r: #回車,也就是Enter鍵
\t: #水平輸出退格鍵,也就是Tab鍵
\v: #垂直輸出退格鍵,也就是Tab鍵
#注意:print 和 printf 的主要區別在有 printf 是標準的格式化輸出,必須手動指定換行和tab.
在進行實驗之前,首先建立一個檔案,來做測試用
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
例項1: 通過 printf
函式列印文字內容
printf命令,如果不指定輸出格式,則會把所有輸出內容連在一起輸出,其實文字的輸出本身就是這樣的,cat等文字輸出命令之所以可以按照格式漂亮的輸出,那是因為cat命令已經設定了輸出格式.
[[email protected] ~]# printf '%s' $(cat lyshark.log)
IDNAMEAGEGenderMark1WR22m1002LC26m903LY23m884XDL40b100
例項2: 通過 printf
格式化後輸出一段文字
[[email protected] ~]# printf '%s\t %s\t %s\t %s\t %s\t \n' $(cat lyshark.log)
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
例項3: 通過 printf
按照整數型和浮點型輸出,則需要修改
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# printf '%i\t %s\t %8.2f\t %s\t %s\t \n' $(cat lyshark.log |grep -v ID)
1 WR 22.00 m 100
2 LC 26.00 m 90
3 LY 23.00 m 88
4 XDL 40.00 b 100
Awk 正則表達工具
awk是一種程式語言,用於在linux/unix下對文字和資料進行處理,資料可以來自標準輸入(stdin),一個或多個檔案,或其它命令的輸出.它支援使用者自定義函式和動態正則表示式等先進功能,是linux/unix下的一個強大程式設計工具,它在命令列中使用,但更多是作為指令碼來使用.awk有很多內建的功能,比如陣列、函式等,這是它和C語言的相同之處,靈活性是awk最大的優勢.
在開始看例子之前,老樣子,你懂的
[[email protected] ~]# awk --help
Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...
命令語法:[ awk '條件1{動作1} 條件2{動作2} ....' 檔名 ]
條件:一般使用關係表示式作為條件
x>10 判斷x變數是否大於10
x==y 判斷變數x是否等於變數y
A ~ B 判斷字串A中是否包含能匹配B表示式的字串
A!~ B 判斷字串A中是否不包含能匹配B表示式的字串
在進行實驗之前,首先建立一個檔案,來做測試用
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
◆awk常用例子◆
例項1: 使用awk格式化輸出第二列和第三列的內容
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# awk '{ printf $2 "\t" $3 "\n" }' lyshark.log
NAME AGE
WR 22
LC 26
LY 23
XDL 40
例項2: 通過awk命令擷取Size和Used命令的顯示列
[[email protected] ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 8.0G 1.2G 6.9G 15% /
devtmpfs 98M 0 98M 0% /dev
tmpfs 110M 0 110M 0% /dev/shm
tmpfs 110M 5.5M 104M 5% /run
tmpfs 110M 0 110M 0% /sys/fs/cgroup
/dev/sda1 1014M 130M 885M 13% /boot
tmpfs 22M 0 22M 0% /run/user/0
[[email protected] ~]# df -h |awk '{ printf $2 "\t" $3 "\n" }'
Size Used
8.0G 1.2G
98M 0
110M 0
110M 5.5M
110M 0
1014M 130M
22M 0
◆begin 與 end◆
BEGIN是awk的保留字,是一種特殊的條件型別.BEGIN的執行時機是 "在awk程式一開始時,尚未讀取任何資料之前執行",一旦BEGIN後的動作執行一次,當awk開始從檔案中讀入資料,BEGIN的條件就不再成立,所以BEGIN定義的動作只能被執行一次,例如:
下面的,整個動作定義了兩個動作,先列印 "執行語句前,執行我" 然後輸出過濾後的2和4列
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# awk 'BEGIN{ printf "執行語句前,執行我 \n" }{ printf $2 "\t" $4 "\n" }' lyshark.log
執行語句前,執行我
NAME Gender
WR m
LC m
LY m
XDL b
END也是awk保留字,不過剛好和BEGIN相反,END是在awk程式處理完所有資料,即將結束時執行.END後的動作只在程式結束時執行一次.
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# awk 'END{ printf "執行語句結束後,執行我 \n" }{ printf $2 "\t" $4 "\n" }' lyshark.log
NAME Gender
WR m
LC m
LY m
XDL b
執行語句結束後,執行我
BEGIN與END連用,以下例子也就是實現了,開始前執行列印 "執行語句前,先執行我",結束時執行列印 "執行語句後,在執行我"
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# awk 'BEGIN{ printf "執行語句前,先執行我 \n" }END{ printf "執行語句後,在執行我 \n"}{ printf $2 "\t"
$4 "\n" }' lyshark.log
執行語句前,先執行我
NAME Gender
WR m
LC m
LY m
XDL b
執行語句後,在執行我
◆awk關係運算◆
關係運算符:設定條件,符合執行不符合不執行,下面設定條件為AGE欄位>=25歲的列出
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# cat lyshark.log | grep -v ID | awk '$3 >=25 {print $1 "\t" $2}'
2 LC
4 XDL
◆awk正則搜尋◆
awk是列提取命令,第一步的動作卻是先讀入第一行,整個執行步驟:
⦁ 如果有BEGIN條件,則先執行BEGIN定義動作.
⦁ 如果沒有BEGIN條件,則先讀入第一行,把第一行的資料依次賦成$0 $1 $2 $3 …等變數,$0 代表整行資料,$1 則為第一個欄位,依次類推.
⦁ 讀入下一行,重複賦值變數,並列印資料.
指定搜尋: 正則搜尋第2列NAME欄位,包含XDL的行,並打印出AGE列對應的值
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# awk '$2 ~/XDL/ {printf $3 "\n"}' lyshark.log
40
[[email protected] ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 8.0G 1.2G 6.9G 15% /
devtmpfs 98M 0 98M 0% /dev
tmpfs 110M 0 110M 0% /dev/shm
tmpfs 110M 5.5M 104M 5% /run
tmpfs 110M 0 110M 0% /sys/fs/cgroup
/dev/sda1 1014M 130M 885M 13% /boot
tmpfs 22M 0 22M 0% /run/user/0
[[email protected] ~]# df -h | grep -v "Filesystem" | awk ' $1 ~/sda1/ {print $2}'
1014M
全域性搜尋: 正則全域性搜尋包含WR的欄位行,並列印本行
[[email protected] ~]# cat lyshark.log
ID NAME AGE Gender Mark
1 WR 22 m 100
2 LC 26 m 90
3 LY 23 m 88
4 XDL 40 b 100
[[email protected] ~]# cat lyshark.log | awk '/WR/ {printf $0 "\n"}'
1 WR 22 m 100
遮蔽顯示: 檢視 df 的真實分割槽的使用情況,不看光碟和虛擬磁碟
[[email protected] ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 8.0G 1.2G 6.9G 15% /
devtmpfs 98M 0 98M 0% /dev
tmpfs 110M 0 110M 0% /dev/shm
tmpfs 110M 5.5M 104M 5% /run
tmpfs 110M 0 110M 0% /sys/fs/cgroup
/dev/sda1 1014M 130M 885M 13% /boot
tmpfs 22M 0 22M 0% /run/user/0
[[email protected] ~]# df -h | awk '/sda[0-9]/ {printf $1 "\t" $5"\n"}'
/dev/sda1 13%
◆awk內建變數◆
例項1: 通過內建變數 FS=":"
定義分隔符,列印/etc/passwd檔案的第1列和第3列
[[email protected] ~]# cat /etc/passwd |grep "/bin/bash"
root:x:0:0:root:/root:/bin/bash
[[email protected] ~]# cat /etc/passwd |grep "/bin/bash" | \
> awk 'BEGIN {FS=":"} {printf $1 "\t" $3 "\n"}'
root 0
例項2: 列印行內容的同時,打印出行號(NR變數),和欄位數(NF變數)
[[email protected] ~]# cat /etc/passwd | grep "/bin/bash" |
\ awk 'BEGIN{FS=":"} {print $1 "\t" $3 "\t" "行號: " NR "\t" "
欄位數: " NF}'
root 0 行號: 1 欄位數: 7
例項3: 列印行內容,首先判斷 $1==sshd
然後再列印本行的行號等資訊
[[email protected] ~]# cat /etc/passwd | grep "/sbin/nologin" |
\ awk 'BEGIN{FS=":"}$1=="sshd" {print $1 "\t" $3 "\t" "行號
: " NR "\t" "欄位數: " NF}'
sshd 74 行號: 13 欄位數: 7
例項4: 一個分割槽統計的小例子
[[email protected] ~]# df -h |grep -v "Filesystem" | \
awk '$1=="/dev/sda1" {print $1 "\t" $5 "\t" "行號:" NR "\t" "欄位數:" NF }'
/dev/sda1 13% 行號:6 欄位數:6
◆awk流程控制◆
在awk程式設計中,因為命令語句非常長,輸入格式時需要注意以下內容:
⦁ 多個條件{動作}可以用空格分割,也可以用回車分割.
⦁ 在一個動作中,如果需要執行多個命令,需要用";"分割,或用回車分割.
⦁ 在awk中,變數的賦值與呼叫都不需要加入"$"符.
⦁ 條件中判斷兩個值是否相同,請使用"==",以便和變數賦值進行區分.
例項1: 將第2行,到第4行,的內容加起來,最後輸出結果
[[email protected] ~]# cat lyshark.log
ID NAME AGE SEX LINUX
1 LY 18 boy 100
2 SC 30 man 150
3 WR 22 man 90
4 ZSX 55 boy 96
[[email protected] ~]# awk 'NR==2{x=$3} NR==3{y=$3} NR==4{z=$3} {totle=x+y+z;print "Totle is:" totle}' lyshark.log
Totle is:0
Totle is:18
Totle is:48
Totle is:70
Totle is:70
[[email protected] ~]# awk 'NR==2{x=$3} NR==3{y=$3} NR==4{z=$3;totle=x+y+z;print "Totle is:" totle}' lyshark.log
Totle is:70
例項2: 統計AGE列,將年齡小於25歲的任過濾出來,並顯示 is young man!
[[email protected] ~]# cat lyshark.log
ID NAME AGE SEX LINUX
1 LY 18 boy 10
2 SC 30 man 50
3 WR 22 man 90
4 ZSX 55 boy 96
[[email protected] ~]# cat lyshark.log | awk '{if (NR >= 2){if ($3 < 25) printf $2 " IS Young Man! \n"}}'
LY IS Young Man!
WR IS Young Man!
例項3: 統計LINUX列,當出現大於80分的,列印到螢幕上 is good man!
[[email protected] ~]# cat lyshark.log
ID NAME AGE SEX LINUX
1 LY 18 boy 10
2 SC 30 man 50
3 WR 22 man 90
4 ZSX 55 boy 96
[[email protected] ~]# cat lyshark.log | awk 'NR>=2 {temp=$5} temp>80 {printf $2 "IS Good Man!\n"}'
WRIS Good Man!
ZSXIS Good Man!
◆awk函式編寫◆
例項1: 通過定義的函式格式,去匹配並傳遞引數
[[email protected] ~]# cat lyshark.log
ID NAME AGE SEX LINUX
1 LY 18 boy 10
2 SC 30 man 50
3 WR 22 man 90
4 ZSX 55 boy 96
[[email protected] ~]# cat lyshark.log | awk 'function lyshark(x,y) {printf x "\t" y "\n"}{lyshark($2,$5)}'
NAME LINUX
LY 10
SC 50
WR 90
ZSX 96
例項2: awk中呼叫指令碼,對於小的單行程式來說,將指令碼作為命令列自變數傳遞給awk是非常簡單的,而對於多行程式就比較難處理.當程式是多行的時候,使用外部指令碼是很適合的.首先在外部檔案中寫好指令碼,然後可以使用awk的-f選項,使其讀入指令碼並且執.
[[email protected] ~]# cat passwd.awk
BEGIN {FS=":"}
{print $1 "\t" $3}
[[email protected] ~]# cat /etc/passwd | awk -f passwd.awk
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
operator 11
games 12
ftp 14
nobody 99
systemd-network 192
dbus 81
polkitd 999
sshd 74
postfix 89
chrony 998
diff/patch 檔案比對
什麼時候會用到檔案的比對啊? 通常是『同一個套裝軟體的不同版本之間,比較配置檔案的差異』,很多時候所謂的檔案比對,通常是用在 ASCII 純文字檔的比對上的,那麼比對檔案最常見的就是 diff .
diff命令在最簡單的情況下,比較給