1. 程式人生 > >Linux正則與文字處理工具(10)

Linux正則與文字處理工具(10)

正則表示式 (Regular Expression, RE, 或稱為常規表示式)是通過一些特殊字元的排列,用於『查詢/替換/刪除』一行或多行文字或字串,簡單的說,正則表示式就是用在字串的處理上面的一種『表示公式』,正則表示式並不是一個工具程式,而是一個對字串處理的標準依據,如果您想要以正則表示式的方式處理字串,就得要使用支援正則表示式的工具程式才行,這類的工具程式很多,例如 vi,vim,sed,awk,gawk,egrep等.

正則表示式,對於系統管理員來說是非常重要的,因為系統會產生很多的資訊,這些資訊有的重要有的僅是警告,此時管理員可以通過正則表示式來過濾出相應的我們需要的欄位,你最好掌握這門技術,會對將來的資料分析,主機管理起到很大的幫助.



基礎正則表示式

在上一章說過正則表示式和萬用字元的區別,(正則表示式用來在檔案中匹配符合條件的字串,而萬用字元則是用來匹配符合條件的檔名)嗎? 其實這種區別只在Shell當中適用,因為用來在檔案當中搜尋字串的命令,如 grep、awk、sed 等命令可以支援正則表示式,而在系統當中搜尋檔案的命令,如 ls、find、cp 這些命令不支援正則表示式,所以只能使用shell自己的萬用字元來進行匹配了.

首先我們先來學習一下基礎的正則表示式吧,下面是我們常用的正則語法,我會給每一個語法,舉一個小例子,下面我們開始學習吧.

blockchain

例項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效果是相同的,使用哪一個都一個樣.

熟悉了基礎正規表示式之後,再來看這個擴充套件正則表示式,是不是很輕鬆啊,親,下面我們就來分別說明這幾個符號的使用規則吧.

blockchain

例項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◆

blockchain

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關係運算◆

blockchain

關係運算符:設定條件,符合執行不符合不執行,下面設定條件為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內建變數◆

blockchain

例項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命令在最簡單的情況下,比較給