Linux文字三劍客超詳細教學---grep、sed、awk

2020-08-16 21:05:27

Linux文字三劍客超詳細教學---grep、sed、awk

  awk、grep、sed是linux操作文字的三大利器,合稱文字三劍客,也是必須掌握的linux命令之一。三者的功能都是處理文字,但側重點各不相同,其中屬awk功能最強大,但也最複雜。grep更適合單純的查詢或匹配文字,sed更適合編輯匹配到的文字,awk更適合格式化文字,對文字進行較複雜格式處理。

1、grep

1.1 什麼是grep和egrep

  Linux系統中grep命令是一種強大的文字搜尋工具,它能使用正則表達式搜尋文字,並把匹配的行列印出來(匹配到的標紅)。grep全稱是Global Regular Expression Print,表示全域性正則表達式版本,它的使用許可權是所有使用者。

  grep的工作方式是這樣的,它在一個或多個檔案中搜尋字串模板。如果模板包括空格,則必須被參照,模板後的所有字串被看作檔名。搜尋的結果被送到標準輸出,不影響原檔案內容。

  grep可用於shell指令碼,因爲grep通過返回一個狀態值來說明搜尋的狀態,如果模板搜尋成功,則返回0,如果搜尋不成功,則返回1,如果搜尋的檔案不存在,則返回2。我們利用這些返回值就可進行一些自動化的文字處理工作。

  egrep = grep -E:擴充套件的正則表達式 (除了\< , \> , \b 使用其他正則都可以去掉\)

 

1.2 使用grep

1.2.1 命令格式

1

grep [option] pattern file

 

1.2.2 命令功能

用於過濾/搜尋的特定字元。可使用正則表達式能多種命令配合使用,使用上十分靈活。

 

1.2.3 命令參數

常用參數已加粗

  •  -A<顯示行數>:除了顯示符合範本樣式的那一列之外,並顯示該行之後的內容。
  •  -B<顯示行數>:除了顯示符合樣式的那一行之外,並顯示該行之前的內容。
  •  -C<顯示行數>:除了顯示符合樣式的那一行之外,並顯示該行之前後的內容。
  •  -c:統計匹配的行數
  •  -e :實現多個選項間的邏輯or 關係
  •  -E:擴充套件的正則表達式
  •  -f FILE:從FILE獲取PATTERN匹配
  •  -F :相當於fgrep
  •  -i --ignore-case #忽略字元大小寫的差別。
  •  -n:顯示匹配的行號
  •  -o:僅顯示匹配到的字串
  •  -q: 靜默模式,不輸出任何資訊
  •  -s:不顯示錯誤資訊。
  •  -v:顯示不被pattern 匹配到的行,相當於[^] 反向匹配
  •  -w :匹配 整個單詞

 

1.3 grep實戰演示

實戰演示

 1:查詢指定進程和個數

[root@aly-centos7 /]# ps -ef | grep nginx
root     14475 14272  0 13:21 pts/0    00:00:00 grep --color=auto nginx
[root@aly-centos7 /]# ps -ef | grep -c nginx
1

 檢視多個檔案相同的部分

檔案內容:
[root@aly-centos7 /]# cat passwd1
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-bus-proxy:x:999:998:systemd Bus Proxy:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:998:997:User for polkitd:/:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
[root@aly-centos7 /]# cat passwd2
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
[root@aly-centos7 /]#cat passwd3
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
過濾結果:
[root@aly-centos7 /]# cat passwd1 | grep -f passwd2 | grep -f passwd3
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
[root@aly-centos7 /]#
最後結果顯示三個檔案相同的部分

 從單個和多個檔案查詢指定內容並顯示行號

[root@aly-centos7 /]# cat passwd2
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
[root@aly-centos7 /]# cat passwd3
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
root,root
root123
[root@aly-centos7 /]# grep -n "root" passwd2
1:root:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/root:/sbin/nologin
[root@aly-centos7 /]# grep -n "root" passwd2 passwd3
passwd2:1:root:x:0:0:root:/root:/bin/bash
passwd2:10:operator:x:11:0:operator:/root:/sbin/nologin
passwd3:1:root:x:0:0:root:/root:/bin/bash
passwd3:5:operator:x:11:0:operator:/root:/sbin/nologin
passwd3:6:root,root
passwd3:7:root123
[root@aly-centos7 /]#

 

 指定字元查詢開頭,非開頭,結尾的內容

[root@aly-centos7 /]# grep "^r" passwd3      #查詢指定字元開頭
root:x:0:0:root:/root:/bin/bash
root,root
root123
[root@aly-centos7 /]# grep "^[^r]" passwd3  #查詢非指定字元開頭
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
[root@aly-centos7 /]# grep "n$" passwd3      #查詢指定結尾
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
[root@aly-centos7 /]#

 

 過濾指定日誌裏面的ip個數

[root@aly-centos7 /]#cat qq.log | grep -c "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}"
130205

 

 過濾指定路徑下所以檔案裏面包含指定字元內容

 

[root@aly-centos7 /]# grep -r -n "root" /etc/
/etc/logrotate.d/ppp:9: create 0600 root root
/etc/logrotate.d/mysql:9:# In case the root user has a password, then you
/etc/logrotate.d/mysql:10:# have to create a /root/.my.cnf configuration file
/etc/logrotate.d/mysql:15:# user= root
/etc/logrotate.d/mysql:19:# ATTENTION: The /root/.my.cnf file should be readable
/etc/logrotate.d/mysql:20:# _ONLY_ by root !
/etc/logrotate.d/mysql-mmm:8:    create 640 root adm
/etc/logrotate.d/wpa_supplicant:5:    create 0600 root root
/etc/logrotate.d/yum:6:    create 0600 root root
/etc/rsyncd.conf:9:# use chroot = yes
/etc/statetab:5:# See $STATE_LABEL in /etc/sysconfig/readonly-root
/etc/statetab:9:#   /root
/etc/group:1:root:x:0:
/etc/group:49:dockerroot:x:991:
/etc/passwd-:1:root:x:0:0:root:/root:/bin/bash
/etc/passwd-:10:operator:x:11:0:operator:/root:/sbin/nologin
Binary file /etc/aliases.db matches
/etc/mime.types:351:application/vnd.cyan.dean.root+xml
/etc/mime.types:382:application/vnd.dvb.notif-aggregate-root+xml

 2、正則表達式

2.1 認識正則

(1)介紹

  正則表達式應用廣泛,在絕大多數的程式語言都可以完美應用,在Linux中,也有着極大的用處。

  使用正則表達式,可以有效的篩選出需要的文字,然後結合相應的支援的工具或語言,完成任務需求。

  在本篇部落格中,我們使用grep/egrep來完成對正則表達式的呼叫

 

(2)正則表達式型別

正則表達式可以使用正則表達式引擎實現,正則表達式引擎是解釋正則表達式模式並使用這些模式匹配文字的基礎軟體。

在Linux中,常用的正則表達式有:

  •  POSIX 基本正則表達式(BRE)引擎
  •  POSIX 擴充套件正則表達式(BRE)引擎

 

2.2 基本正則表達式

2.2.1 匹配字元

(1)格式

  •  . 匹配任意單個字元,不能匹配空行
  •   [] 匹配指定範圍內的任意單個字元
  •   [^] 取反
  •   [:alnum:] 或 [0-9a-zA-Z]
  •   [:alpha:] 或 [a-zA-Z]
  •   [:upper:] 或 [A-Z]
  •   [:lower:] 或 [a-z]
  •   [:blank:] 空白字元(空格和製表符)
  •   [:space:] 水平和垂直的空白字元(比[:blank:]包含的範圍廣)
  •   [:cntrl:] 不可列印的控制字元(退格、刪除、警鈴...)
  •   [:digit:] 十進制數位 或[0-9]
  •   [:xdigit:]十六進制數位
  •   [:graph:] 可列印的非空白字元
  •   [:print:] 可列印字元
  •   [:punct:] 標點符號

(2)演示

 

2.2.2 設定次數

(1)格式

  •  *  匹配前面的字元任意次,包括0次,貪婪模式:儘可能長的匹配
  •  .*  任意長度的任意字元,不包括0次
  •  \?  匹配其前面的字元0 或 1次
  •  \+  匹配其前面的字元至少1次
  •  \{n\}  匹配前面的字元n次
  •  \{m,n\}  匹配前面的字元至少m 次,至多n次
  •  \{,n\}  匹配前面的字元至多n次
  •  \{n,\}  匹配前面的字元至少n次

(2)演示

 

2.2.3 位置錨定:定位出現的位置

(1)格式

  •  ^  行首錨定,用於模式的最左側
  •  $  行尾錨定,用於模式的最右側
  •  ^PATTERN$,用於模式匹配整行
  •  ^$ 空行
  •  ^[[:space:]].*$  空白行
  •  \< 或 \b  詞首錨定,用於單詞模式的左側
  •  \> 或 \b  詞尾錨定;用於單詞模式的右側
  •  \<PATTERN\>

(2)演示

 

2.2.4 分組和後向參照

(1)格式

① 分組:\(\) 將一個或多個字元捆綁在一起,當作一個整體進行處理

  分組括號中的模式匹配到的內容會被正則表達式引擎記錄於內部的變數中,這些變數的命名方式爲: \1, \2, \3, ...

② 後向參照

參照前面的分組括號中的模式所匹配字元,而非模式本身

\1 表示從左側起第一個左括號以及與之匹配右括號之間的模式所匹配到的字元

\2 表示從左側起第2個左括號以及與之匹配右括號之間的模式所匹配到的字元,以此類推

\& 表示前面的分組中所有字元

③ 流程分析如下:

(2)演示

 

2.3 擴充套件正則表達式

(1)字元匹配:

  •  .  任意單個字元
  •  []  指定範圍的字元
  •  [^] 不在指定範圍的字元
  •    次數匹配:
  •  * :匹配前面字元任意次
  •  ?  : 0 或1次
  •  + :1 次或多次
  •  {m} :匹配m次 次
  •  {m,n} :至少m ,至多n次

(2)位置錨定:

  •  ^ : 行首
  •  $ : 行尾
  •  \<, \b : 語首
  •  \>, \b : 語尾
  •    分組:()
  •  後向參照:\1, \2, ...

(3)總結

  除了\<, \b : 語首、\>, \b : 語尾;使用其他正則都可以去掉\;上面有演示案例,不在進行演示

 

3、sed

3.1 認識sed

  sed 是一種流編輯器,它一次處理一內容。處理時,把當前處理的行儲存在臨時緩衝區中,稱爲「模式空間」(patternspace ),接着用sed 命令處理緩衝區中的內容,處理完成後,把緩衝區的內容送往螢幕。然後讀入下行,執行下一個回圈。如果沒有使諸如‘D’ 的特殊命令,那會在兩個回圈之間清空模式空間,但不會清空保留空間。這樣不斷重複,直到檔案末尾。檔案內容並沒有改變,除非你使用重定向儲存輸出或-i

  功能:主要用來自動編輯一個或多個檔案, 簡化對檔案的反覆 反復操作

 

3.2 使用sed

3.2.1 命令格式

1

sed [options] '[地址定界] command' file(s)

  

3.2.2 常用選項options

  •  -n:不輸出模式空間內容到螢幕,即不自動列印,只列印匹配到的行
  •  -e:多點編輯,對每行處理時,可以有多個Script
  •  -f:把Script寫到檔案當中,在執行sed時-f 指定檔案路徑,如果是多個Script,換行寫
  •  -r:支援擴充套件的正則表達式
  •  -i:直接將處理的結果寫入檔案
  •  -i.bak:在將處理的結果寫入檔案之前備份一份

 

3.2.3 地址定界

  •  不給地址:對全文進行處理
  •  單地址:
    •  #: 指定的行
    •  /pattern/:被此處模式所能夠匹配到的每一行
  •  地址範圍:
    •  #,#
    •  #,+#
    •  /pat1/,/pat2/
    •  #,/pat1/
  •  ~:步進
    •   sed -n '1~2p'  只列印奇數行 (1~2 從第1行,一次加2行)
    •   sed -n '2~2p'  只列印偶數行

 

3.2.4 編輯命令command

  •  d:刪除模式空間匹配的行,並立即啓用下一輪回圈
  •  p:列印當前模式空間內容,追加到預設輸出之後
  •  a:在指定行後面追加文字,支援使用\n實現多行追加
  •  i:在行前面插入文字,支援使用\n實現多行追加
  •  c替換行爲單行或多行文字,支援使用\n實現多行追加
  •  w:儲存模式匹配的行至指定檔案
  •  r:讀取指定檔案的文字至模式空間中匹配到的行後
  •  =:爲模式空間中的行列印行號
  •  !:模式空間中匹配行取反處理
  •  s///查詢替換,支援使用其它分隔符,如:s@@@,s###;
    •  加g表示行內全域性替換;
    •  在替換時,可以加一下命令,實現大小寫轉換
    •  \l:把下個字元轉換成小寫。
    •  \L:把replacement字母轉換成小寫,直到\U或\E出現。
    •  \u:把下個字元轉換成大寫。
    •  \U:把replacement字母轉換成大寫,直到\L或\E出現。
    •  \E:停止以\L或\U開始的大小寫轉換

 

3.3 sed用法演示

3.3.1 常用選項options演示

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

[root@along ~]# cat demo

aaa

bbbb

AABBCCDD

[root@along ~]# sed "/aaa/p" demo  #匹配到的行會列印一遍,不匹配的行也會列印

aaa

aaa

bbbb

AABBCCDD

[root@along ~]# sed -n "/aaa/p" demo  #-n不顯示沒匹配的行

aaa

[root@along ~]# sed -e "s/a/A/" -e "s/b/B/" demo  #-e多點編輯

Aaa

Bbbb

AABBCCDD

[root@along ~]# cat sedscript.txt

s/A/a/g

[root@along ~]# sed -f sedscript.txt demo  #-f使用檔案處理

aaa

bbbb

aaBBCCDD

[root@along ~]# sed -i.bak "s/a/A/g" demo  #-i直接對檔案進行處理

[root@along ~]# cat demo

AAA

bbbb

AABBCCDD

[root@along ~]# cat demo.bak

aaa

bbbb

AABBCCDD

  

3.3.2 地址界定演示

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

[root@along ~]# cat demo

aaa

bbbb

AABBCCDD

[root@along ~]# sed -n "p" demo  #不指定行,列印全文

aaa

bbbb

AABBCCDD

[root@along ~]# sed "2s/b/B/g" demo  #替換第2行的b->B

aaa

BBBB

AABBCCDD

[root@along ~]# sed -n "/aaa/p" demo

aaa

[root@along ~]# sed -n "1,2p" demo  #列印1-2行

aaa

bbbb

[root@along ~]# sed -n "/aaa/,/DD/p" demo

aaa

bbbb

AABBCCDD

[root@along ~]# sed -n "2,/DD/p" demo

bbbb

AABBCCDD

[root@along ~]# sed "1~2s/[aA]/E/g" demo  #將奇數行的a或A替換爲E

EEE

bbbb

EEBBCCDD

  

3.3.3 編輯命令command演示

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

[root@along ~]# cat demo

aaa

bbbb

AABBCCDD

[root@along ~]# sed "2d" demo  #刪除第2行

aaa

AABBCCDD

[root@along ~]# sed -n "2p" demo  #列印第2行

bbbb

[root@along ~]# sed "2a123" demo  #在第2行後加123

aaa

bbbb

123

AABBCCDD

[root@along ~]# sed "1i123" demo  #在第1行前加123

123

aaa

bbbb

AABBCCDD

[root@along ~]# sed "3c123\n456" demo  #替換第3行內容

aaa

bbbb

123

456

[root@along ~]# sed -n "3w/root/demo3" demo  #儲存第3行的內容到demo3檔案中

[root@along ~]# cat demo3

AABBCCDD

[root@along ~]# sed "1r/root/demo3" demo  #讀取demo3的內容到第1行後

aaa

AABBCCDD

bbbb

AABBCCDD

[root@along ~]# sed -n "=" demo  #=列印行號

1

2

3

[root@along ~]# sed -n '2!p' demo  #列印除了第2行的內容

aaa

AABBCCDD

[root@along ~]# sed 's@[a-z]@\u&@g' demo  #將全文的小寫字母替換爲大寫字母

AAA

BBBB

AABBCCDD

  

3.4 sed高階編輯命令

(1)格式

  •  h:把模式空間中的內容覆蓋至保持空間中
  •  H:把模式空間中的內容追加至保持空間中
  •  g:從保持空間取出數據覆蓋至模式空間
  •  G:從保持空間取出內容追加至模式空間
  •  x:把模式空間中的內容與保持空間中的內容進行互換
  •  n:讀取匹配到的行的下一行覆蓋 至模式空間
  •  N:讀取匹配到的行的下一行追加 至模式空間
  •  d:刪除模式空間中的行
  •  D:刪除 當前模式空間開端至\n 的內容(不再傳 至標準輸出),放棄之後的命令,但是對剩餘模式空間重新執行sed

 

(2)一個案例+示意圖演示

① 案例:倒序輸出文字內容

1

2

3

4

5

6

7

8

[root@along ~]# cat num.txt

One

Two

Three

[root@along ~]# sed '1!G;h;$!d' num.txt

Three

Two

One

② 示意圖如下:

③ 總結模式空間與保持空間關係:

保持空間是模式空間一個臨時存放數據的緩衝區,協助模式空間進行數據處理

 

(3)演示

① 顯示偶數行

1

2

3

4

5

[root@along ~]# seq 9 |sed -n 'n;p'

2

4

6

8

② 倒序顯示

1

2

3

4

5

6

7

8

9

10

[root@along ~]# seq 9 |sed  '1!G;h;$!d'

9

8

7

6

5

4

3

2

1

③ 顯示奇數行

1

2

3

4

5

6

[root@along ~]# seq 9 |sed 'H;n;d'

1

3

5

7

9

④ 顯示最後一行

1

2

[root@along ~]# seq 9| sed 'N;D'

9

⑤ 每行之間加空行

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

[root@along ~]# seq 9 |sed 'G'

1

 

2

 

3

 

4

 

5

 

6

 

7

 

8

 

9

 

---

 ⑥ 把每行內容替換成空行

1

2

3

4

5

6

7

8

9

10

11

[root@along ~]# seq 9 |sed "g"

 

 

 

 

 

 

 

 

 

---

 ⑦ 確保每一行下面 下麪都有一個空行

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

[root@along ~]# seq 9 |sed '/^$/d;G'

1

 

2

 

3

 

4

 

5

 

6

 

7

 

8

 

9

sed實戰演示

查詢:

 指定行區間查詢以root開頭的內容

[root@aly-centos7 /]# sed -n '1,5{/^root/p}' passwd2
root:x:0:0:root:/root:/bin/bash
[root@aly-centos7 /]#

 匹配行之後增加顯示內容

[root@aly-centos7 /]# cat passwd3
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
root,root
root123
[root@aly-centos7 /]# sed -n '/3/,$p' passwd3 #顯示第一次匹配到的3到最行一行輸出
adm:x:3:4:adm:/var/adm:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
root,root
root123
[root@aly-centos7 /]# sed -n '/3/,+1p' passwd3#顯示第一次匹配到的3到向下1行輸出
adm:x:3:4:adm:/var/adm:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
root123

 文字逆向排序輸出

[root@aly-centos7 /]# cat passwd2
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
[root@aly-centos7 /]# sed '1!G;h;$!d' passwd2 #逆向排序
operator:x:11:0:operator:/root:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
halt:x:7:0:halt:/sbin:/sbin/halt
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
sync:x:5:0:sync:/sbin:/bin/sync
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
root:x:0:0:root:/root:/bin/bash

 顯示行號(空行也顯示)或(空行不顯示行號)

operator:x:11:0:operator:/root:/sbin/nologin
[root@aly-centos7 /]#
[root@aly-centos7 /]# cat passwd2
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin


operator:x:11:0:operator:/root:/sbin/nologin
[root@aly-centos7 /]# sed '=' passwd2   #不遮蔽空行
1
root:x:0:0:root:/root:/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
9
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10

11

12
operator:x:11:0:operator:/root:/sbin/nologin
[root@aly-centos7 /]# sed '/./=' passwd2   #遮蔽空行
1
root:x:0:0:root:/root:/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
9
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin


12
operator:x:11:0:operator:/root:/sbin/nologin

 顯示檔案總行數

[root@aly-centos7 /]# grep -n "" passwd3
1:root:x:0:0:root:/root:/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:operator:x:11:0:operator:/root:/sbin/nologin
6:root,root
7:root123
[root@aly-centos7 /]# sed -n '$=' passwd3
7

 顯示偶數和奇數行

[root@aly-centos7 /]# grep -n "" passwd3
1:root:x:0:0:root:/root:/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:operator:x:11:0:operator:/root:/sbin/nologin
6:root,root
7:root123
[root@aly-centos7 /]# sed -n 'p;n' passwd3    #奇數行
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
root123
[root@aly-centos7 /]# sed -n '1~2p' passwd3   #奇數行
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
root123
[root@aly-centos7 /]# sed -n 'n;p' passwd3    #偶數行
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
root,root
[root@aly-centos7 /]# sed -n '2~2p' passwd3  #偶數行
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
root,root
[root@aly-centos7 /]#

 檔案中每行內容逆向顯示

[root@aly-centos7 /]# cat passwd2
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
%shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
$halt:x:7:0:halt:/sbin:/sbin/halt
#$mail:x:8:12:mail:/var/spool/mail:/sbin/nologin


operator:x:11:0:operator:/root:/sbin/nologin
1234567890
9876543210
[root@aly-centos7 /]# sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//' passwd2
hsab/nib/:toor/:toor:0:0:x:toor
nigolon/nibs/:nib/:nib:1:1:x:nib
nigolon/nibs/:nibs/:nomead:2:2:x:nomead
nigolon/nibs/:mda/rav/:mda:4:3:x:mda
nigolon/nibs/:dpl/loops/rav/:pl:7:4:x:pl
cnys/nib/:nibs/:cnys:0:5:x:cnys
nwodtuhs/nibs/:nibs/:nwodtuhs:0:6:x:nwodtuhs%
tlah/nibs/:nibs/:tlah:0:7:x:tlah$
nigolon/nibs/:liam/loops/rav/:liam:21:8:x:liam$#


nigolon/nibs/:toor/:rotarepo:0:11:x:rotarepo
0987654321
0123456789
[root@aly-centos7 /]#

 將數位按照「個十百」顯示 

[root@aly-centos7 /]# cat passwd2
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
%shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
$halt:x:7:0:halt:/sbin:/sbin/halt
#$mail:x:8:12:mail:/var/spool/mail:/sbin/nologin


operator:x:11:0:operator:/root:/sbin/nologin
1234567890
9876543210
[root@aly-centos7 /]# sed ':a;s/\B[0-9]\{3\}\>/,&/;ta' passwd2
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
%shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
$halt:x:7:0:halt:/sbin:/sbin/halt
#$mail:x:8:12:mail:/var/spool/mail:/sbin/nologin


operator:x:11:0:operator:/root:/sbin/nologin
1,234,567,890
9,876,543,210
[root@aly-centos7 /]#

刪除:

 刪除指定內容

刪除1-5行內容
[root@aly-centos7 /]# grep -n "" passwd2 | sed '1,5d'
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
9:#$mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10:
11:
12:operator:x:11:0:operator:/root:/sbin/nologin
13:1234567890
14:9876543210
刪除奇數行:
[root@aly-centos7 /]# grep -n "" passwd2 | sed '1~2d'
2:bin:x:1:1:bin:/bin:/sbin/nologin
4:adm:x:3:4:adm:/var/adm:/sbin/nologin
6:sync:x:5:0:sync:/sbin:/bin/sync
8:$halt:x:7:0:halt:/sbin:/sbin/halt
10:
12:operator:x:11:0:operator:/root:/sbin/nologin
14:9876543210
刪除空行
[root@aly-centos7 /]# grep -n "" passwd2
1:root:x:0:0:root:/root:/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
9:#$mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10:
11:
12:operator:x:11:0:operator:/root:/sbin/nologin
13:1234567890
14:9876543210
[root@aly-centos7 /]# grep "" passwd2 | sed '/^$/d'
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
%shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
$halt:x:7:0:halt:/sbin:/sbin/halt
#$mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
1234567890
9876543210
[root@aly-centos7 /]#

 修改:

 指定內容進行替換

將root全部替換成mysql
[root@aly-centos7 /]# grep -n "" passwd3
1:root:x:0:0:root:/root:/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:operator:x:11:0:operator:/root:/sbin/nologin
6:root,root
7:root123
[root@aly-centos7 /]# sed 's/root/mysql/g' passwd3
mysql:x:0:0:mysql:/mysql:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
operator:x:11:0:operator:/mysql:/sbin/nologin
mysql,mysql
mysql123
把數位1全部替換成9
[root@aly-centos7 /]# sed 's/1/9/g' passwd3
root:x:0:0:root:/root:/bin/bash
bin:x:9:9:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
operator:x:99:0:operator:/root:/sbin/nologin
root,root
root923
只替換行中未出現「sbin」字元的時候,將」root「替換成」nginx「
[root@aly-centos7 /]# sed '/sbin/!s/root/nginx/g' passwd3
nginx:x:0:0:nginx:/nginx:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
nginx,nginx
nginx123
root:x:11:0:operator:/root:/sbin/nologin
root1:x:11:0:operator:/root:/sbin/nologin
root2:x:11:0:operator:/root:/sbin/nologin
[root@aly-centos7 /]#

4、awk

4.1 認識awk

  awk是一種程式語言,用於在linux/unix下對文字和數據進行處理。數據可以來自標準輸入(stdin)、一個或多個檔案,或其它命令的輸出。它支援使用者自定義函數和動態正則表達式等先進功能,是linux/unix下的一個強大程式設計工具。它在命令列中使用,但更多是作爲指令碼來使用。awk有很多內建的功能,比如陣列、函數等,這是它和C語言的相同之處,靈活性是awk最大的優勢。

  awk其實不僅僅是工具軟體,還是一種程式語言。不過,本文只介紹它的命令列用法,對於大多數場合,應該足夠用了。

 

4.2 使用awk

4.2.1 語法

1

2

3

awk [options] 'program' var=value file

awk [options] -f programfile var=value file

awk [options] 'BEGIN{ action;… } pattern{ action;… } END{ action;… }' file ...

  

4.2.2 常用命令選項

  •  -F fs:fs指定輸入分隔符,fs可以是字串或正則表達式,如-F:
  •  -v var=value:賦值一個使用者定義變數,將外部變數傳遞給awk
  •  -f scripfile:從指令碼檔案中讀取awk命令

 

4.3 awk變數

變數:內建和自定義變數,每個變數前加 -v 命令選項

4.3.1 內建變數

(1)格式

  •  FS 輸入欄位分隔符預設爲空白字元
  •  OFS 輸出欄位分隔符,預設爲空白字元
  •  RS :輸入記錄分隔符,指定輸入時的換行符,原換行符仍有效
  •  ORS :輸出記錄分隔符,輸出時用指定符號代替換行符
  •  NF :欄位數量,共有多少欄位, $NF參照最後一列,$(NF-1)參照倒數第2列
  •  NR :行號,後可跟多個檔案,第二個檔案行號繼續從第一個檔案最後行號開始
  •  FNR :各檔案分別計數, 行號,後跟一個檔案和NR一樣,跟多個檔案,第二個檔案行號從1開始
  •  FILENAME :當前檔名
  •  ARGC :命令列參數的個數
  •  ARGV :陣列,儲存的是命令列所給定的各參數,檢視參數

 

(2)演示

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

[root@along ~]# cat awkdemo

hello:world

linux:redhat:lalala:hahaha

along:love:youou

[root@along ~]# awk -v FS=':' '{print $1,$2}' awkdemo  #FS指定輸入分隔符

hello world

linux redhat

along love

[root@along ~]# awk -v FS=':' -v OFS='---' '{print $1,$2}' awkdemo  #OFS指定輸出分隔符

hello---world

linux---redhat

along---love

[root@along ~]# awk -v RS=':' '{print $1,$2}' awkdemo

hello

world linux

redhat

lalala

hahaha along

love

you

[root@along ~]# awk -v FS=':' -v ORS='---' '{print $1,$2}' awkdemo

hello world---linux redhat---along love---

[root@along ~]# awk -F: '{print NF}' awkdemo

2

4

3

[root@along ~]# awk -F: '{print $(NF-1)}' awkdemo  #顯示倒數第2列

hello

lalala

love

[root@along ~]# awk '{print NR}' awkdemo awkdemo1

1

2

3

4

5

[root@along ~]# awk END'{print NR}' awkdemo awkdemo1

5

[root@along ~]# awk '{print FNR}' awkdemo awkdemo1

1

2

3

1

2

[root@along ~]# awk '{print FILENAME}' awkdemo

awkdemo

awkdemo

awkdemo

[root@along ~]# awk 'BEGIN {print ARGC}' awkdemo awkdemo1

3

[root@along ~]# awk 'BEGIN {print ARGV[0]}' awkdemo awkdemo1

awk

[root@along ~]# awk 'BEGIN {print ARGV[1]}' awkdemo awkdemo1

awkdemo

[root@along ~]# awk 'BEGIN {print ARGV[2]}' awkdemo awkdemo1

awkdemo1

  

4.3.2 自定義變數

自定義變數( 區分字元大小寫)

(1)-v var=value

① 先定義變數,後執行動作print

1

2

3

4

[root@along ~]# awk -v name="along" -F: '{print name":"$0}' awkdemo

along:hello:world

along:linux:redhat:lalala:hahaha

along:along:love:you

② 在執行動作print後定義變數

1

2

3

4

[root@along ~]# awk -F: '{print name":"$0;name="along"}' awkdemo

:hello:world

along:linux:redhat:lalala:hahaha

along:along:love:you

  

(2)在program 中直接定義

可以把執行的動作放在指令碼中,直接呼叫指令碼 -f

1

2

3

4

5

6

[root@along ~]# cat awk.txt

{name="along";print name,$1}

[root@along ~]# awk -F: -f awk.txt awkdemo

along hello

along linux

along along

  

4.4 printf命令

比print更強大

4.4.1 格式

(1)格式化輸出

1

printf "FORMAT", item1,item2, ...

①  必須指定FORMAT

②  不會自動換行,需要顯式給出換行控制符,\n

③  FORMAT 中需要分別爲後面每個item 指定格式符

 

(2)格式符:與item 一一對應

  •  %c:  顯示字元的ASCII碼
  •  %d, %i:  顯示十進制整數
  •  %e, %E: 顯示科學計數法數值
  •  %f :顯示爲浮點數,小數   %5.1f,帶整數、小數點、整數共5位,小數1位,不夠用空格補上
  •  %g, %G :以科學計數法或浮點形式顯示數值
  •  %s :顯示字串;例:%5s最少5個字元,不夠用空格補上,超過5個還繼續顯示
  •  %u :無符號整數
  •  %%:  顯示% 自身

 

(3)修飾符:放在%c[/d/e/f...]之間

  •  #[.#]:第一個數位控制顯示的寬度;第二個# 表示小數點後精度,%5.1f
  •  -:左對齊(預設右對齊) %-15s
  •  +:顯示數值的正負符號 %+d

 

4.4.2 演示

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

[root@along ~]# awk -F: '{print $1,$3}' /etc/passwd

root 0

bin 1

---第一列顯示小於20的字串;第2列顯示整數並換行

[root@along ~]# awk -F: '{printf "%20s---%u\n",$1,$3}' /etc/passwd

                root---0

                 bin---1

---使用-進行左對齊;第2列顯示浮點數

[root@along ~]# awk -F: '{printf "%-20s---%-10.3f\n",$1,$3}' /etc/passwd

root                ---0.000    

bin                 ---1.000

---使用printf做表格

[root@along ~]# awk -F: 'BEGIN{printf "username            userid\n-----------------------------\n"}{printf "%-20s|%-10.3f\n",$1,$3}' /etc/passwd

username            userid

-----------------------------

root                |0.000    

bin                 |1.000

  

4.5 操作符

4.5.1 格式

  •  算術操作符:
    •  x+y, x-y, x*y, x/y, x^y, x%y
    •  -x:  轉換爲負數
    •  +x:  轉換爲數值
  •  字串操作符:沒有符號的操作符,字串連線
  •  賦值操作符:
    •  =, +=, -=, *=, /=, %=, ^=
    •  ++, --
  •  比較操作符:
    •  ==, !=, >, >=, <, <=
  •  模式匹配符:~ :左邊是否和右邊匹配包含 !~ :是否不匹配
  •  邏輯操作符:與&& ,或|| ,非!
  •  函數呼叫: function_name(argu1, argu2, ...)
  •  條件表達式(三目表達式):selector?if-true-expression:if-false-expression
    •  註釋:先判斷selector,如果符合執行 ? 後的操作;否則執行 : 後的操作

 

4.5.2 演示

(1)模式匹配符

1

2

3

4

5

6

7

8

9

10

11

---查詢以/dev開頭的磁碟資訊

[root@along ~]# df -h |awk -F: '$0 ~ /^\/dev/'

/dev/mapper/cl-root   17G  7.3G  9.7G  43% /

/dev/sda1           1014M  121M  894M  12% /boot

---只顯示磁碟使用狀況和磁碟名

[root@along ~]# df -h |awk '$0 ~ /^\/dev/{print $(NF-1)"---"$1}'

43%---/dev/mapper/cl-root

12%---/dev/sda1

---查詢磁碟大於40%的

[root@along ~]# df -h |awk '$0 ~ /^\/dev/{print $(NF-1)"---"$1}' |awk -F% '$1 > 40'

43%---/dev/mapper/cl-root

  

(2)邏輯操作符

1

2

3

4

5

6

7

8

9

10

[root@along ~]# awk -F: '$3>=0 && $3<=1000 {print $1,$3}' /etc/passwd

root 0

bin 1

[root@along ~]# awk -F: '$3==0 || $3>=1000 {print $1}' /etc/passwd

root

[root@along ~]# awk -F: '!($3==0) {print $1}' /etc/passwd

bin

[root@along ~]# awk -F: '!($0 ~ /bash$/) {print $1,$3}' /etc/passwd

bin 1

daemon 2

  

(3)條件表達式(三目表達式)

1

2

3

[root@along ~]# awk -F: '{$3 >= 1000?usertype="common user":usertype="sysadmin user";print usertype,$1,$3}' /etc/passwd

sysadmin user root 0

common user along 1000

  

4.6 awk PATTERN 匹配部分

4.6.1 格式

PATTERN:根據pattern 條件,過濾匹配的行,再做處理

(1)如果未指定:空模式,匹配每一行

(2)/regular expression/ :僅處理能夠模式匹配到的行,正則,需要用/ / 括起來

(3)relational expression:關係表達式,結果爲「真」纔會被處理

真:結果爲非0值,非空字串

假:結果爲空字串或0值

(4)line ranges:行範圍

  startline(起始行),endline(結束行):/pat1/,/pat2/  不支援直接給出數位,可以有多段,中間可以有間隔

(5)BEGIN/END 模式

  BEGIN{}:  僅在開始處理檔案中的文字之前執行一次

  END{} :僅在文字處理完成之後執行

 

4.6.2 演示

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

[root@along ~]# awk -F: '{print $1}' awkdemo

hello

linux

along

[root@along ~]# awk -F: '/along/{print $1}' awkdemo

along

[root@along ~]# awk -F: '1{print $1}' awkdemo

hello

linux

along

[root@along ~]# awk -F: '0{print $1}' awkdemo

[root@along ~]# awk -F: '/^h/,/^a/{print $1}' awkdemo

hello

linux

along

[root@along ~]# awk -F: 'BEGIN{print "第一列"}{print $1} END{print "結束"}' awkdemo

第一列

hello

linux

along

結束

  

4.7 awk有意思的案例

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

[root@along ~]# seq 10

1

2

3

4

5

6

7

8

9

10

---因爲i=0,爲假,所以不列印

[root@along ~]# seq 10 |awk 'i=0'

---i=1,爲真,所以全部列印

[root@along ~]# seq 10 |awk 'i=1'

1

2

3

4

5

6

7

8

9

10

---只列印奇數行;奇數行i進入時本身爲空,被賦爲!i,即不爲空,所以列印;偶數行i進入時本身不爲空,被賦爲!i,即爲空,所以不列印

[root@along ~]# seq 10 |awk 'i=!i'

1

3

5

7

9

---解釋上一個操作,i在奇偶行的值

[root@along ~]# seq 10 |awk '{i=!i;print i}'

1

0

1

0

1

0

1

0

1

0

---只列印偶數行,是上邊列印奇數行的取反

[root@along ~]# seq 10 |awk '!(i=!i)'

2

4

6

8

10

---只列印偶數行;先對i進行賦值,即不爲空,剛好和列印奇數行相反

[root@along ~]# seq 10 |awk -v i=1 'i=!i'

2

4

6

8

10

  

5、awk高階用法

5.1 awk控制語句—if-else判斷

(1)語法

1

2

if(condition){statement;…}[else statement]  雙分支

if(condition1){statement1}else if(condition2){statement2}else{statement3}  多分支

(2)使用場景:對awk 取得的整行或某個欄位做條件判斷

(3)演示

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

[root@along ~]# awk -F: '{if($3>10 && $3<1000)print $1,$3}' /etc/passwd

operator 11

games 1

[root@along ~]# awk -F: '{if($NF=="/bin/bash") print $1,$NF}' /etc/passwd

root /bin/bash

along /bin/bash

---輸出總列數大於3的行

[root@along ~]# awk -F: '{if(NF>2) print $0}' awkdemo

linux:redhat:lalala:hahaha

along:love:you

---第3列>=1000爲Common user,反之是root or Sysuser

[root@along ~]# awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else{printf "root or Sysuser: %s\n",$1}}' /etc/passwd

root or Sysuser: root

root or Sysuser: bin

Common user: along

---磁碟利用率超過40的裝置名和利用率

[root@along ~]# df -h|awk -F% '/^\/dev/{print $1}'|awk '$NF > 40{print $1,$NF}'

/dev/mapper/cl-root 43

---test=100和>90爲very good; 90>test>60爲good; test<60爲no pass

[root@along ~]# awk 'BEGIN{ test=100;if(test>90){print "very good"}else if(test>60){ print "good"}else{print "no pass"}}'

very good

[root@along ~]# awk 'BEGIN{ test=80;if(test>90){print "very good"}else if(test>60){ print "good"}else{print "no pass"}}'

good

[root@along ~]# awk 'BEGIN{ test=50;if(test>90){print "very good"}else if(test>60){ print "good"}else{print "no pass"}}'

no pass

  

5.2 awk控制語句—while回圈

(1)語法

1

while(condition){statement;…}

注:條件「真」,進入回圈;條件「假」, 退出回圈

 

(2)使用場景

  對一行內的多個欄位逐一類似處理時使用

  對陣列中的各元素逐一處理時使用

 

(3)演示

1

2

3

4

5

6

7

8

9

10

11

12

13

---以along開頭的行,以:爲分隔,顯示每一行的每個單詞和其長度

[root@along ~]# awk -F: '/^along/{i=1;while(i<=NF){print $i,length($i); i++}}' awkdemo

along 5

love 4

you 3

---以:爲分隔,顯示每一行的長度大於6的單詞和其長度

[root@along ~]# awk -F: '{i=1;while(i<=NF) {if(length($i)>=6){print $i,length($i)}; i++}}' awkdemo

redhat 6

lalala 6

hahaha 6

---計算1+2+3+...+100=5050

[root@along ~]# awk 'BEGIN{i=1;sum=0;while(i<=100){sum+=i;i++};print sum}'

5050

  

5.3 awk控制語句—do-while回圈

(1)語法

1

do {statement;…}while(condition)

意義:無論真假,至少執行一次回圈體

 

(2)計算1+2+3+...+100=5050

1

2

[root@along ~]# awk 'BEGIN{sum=0;i=1;do{sum+=i;i++}while(i<=100);print sum}'

5050

  

5.4 awk控制語句—for回圈

(1)語法

1

for(expr1;expr2;expr3) {statement;…}

  

(2)特殊用法:遍歷陣列中的元素

1

for(var in array) {for-body}

  

(3)演示

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

---顯示每一行的每個單詞和其長度

[root@along ~]# awk -F: '{for(i=1;i<=NF;i++) {print$i,length($i)}}' awkdemo

hello 5

world 5

linux 5

redhat 6

lalala 6

hahaha 6

along 5

love 4

you 3

---求男m、女f各自的平均

[root@along ~]# cat sort.txt

xiaoming m 90

xiaohong f 93

xiaohei m 80

xiaofang f 99

[root@along ~]# awk '{m[$2]++;score[$2]+=$3}END{for(i in m){printf "%s:%6.2f\n",i,score[i]/m[i]}}' sort.txt

m: 85.00

f: 96.00

  

5.5 和shell指令碼中較相似的控制語句

5.5.1 switch語句

和shell中的case很像,就不在演示了

1

switch(expression) {case VALUE1 or /REGEXP/:statement1; case VALUE2 or /REGEXP2/: statement2;...; default: statementn}

 

5.5.2 break和continue

1

2

3

4

5

6

---奇數相加

[root@along ~]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}'

2500

---1+2+...+66

[root@along ~]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}'

2145

 

5.5.3 next

next:提前結束對本行處理而直接進入下一行處理(awk 自身回圈)

1

2

3

4

---只列印偶數行

[root@along ~]# awk -F: '{if(NR%2!=0) next; print $1,$3}' /etc/passwd

bin 1

adm 3

  

5.6 awk陣列

5.6.1 關聯陣列:array[index-expression]

(1)可使用任意字串;字串要使用雙引號括起來

(2)如果某陣列元素事先不存在,在參照時,awk 會自動建立此元素,並將其值初始化爲「空串」

(3)若要判斷陣列中是否存在某元素,要使用「index in array」格式進行遍歷

(4)若要遍歷陣列中的每個元素,要使用for 回圈:for(var in array) {for-body}

 

5.6.2 演示

(1)awk使用陣列

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

[root@along ~]# cat awkdemo2

aaa

bbbb

aaa

123

123

123

---去除重複的行

[root@along ~]# awk '!arr[$0]++' awkdemo2

aaa

bbbb

123

---列印檔案內容,和該行重複第幾次出現

[root@along ~]# awk '{!arr[$0]++;print $0,arr[$0]}' awkdemo2

aaa 1

bbbb 1

aaa 2

123 1

123 2

123 3

  分析:把每行作爲下標,第一次進來,相當於print ias...一樣結果爲空,列印空,!取反結果爲1,列印本行,並且++變爲不空,下次進來相同的行就是相同的下標,本來上次的值,!取反爲空,不列印,++變爲不空,所以每次重複進來的行都不列印

 

(2)陣列遍歷

1

2

3

4

5

6

7

8

[root@along ~]# awk 'BEGIN{abc["ceo"]="along";abc["coo"]="mayun";abc["cto"]="mahuateng";for(i in abc){print i,abc[i]}}'

coo mayun

ceo along

cto mahuateng

[root@along ~]# awk '{for(i=1;i<=NF;i++)abc[$i]++}END{for(j in abc)print j,abc[j]}' awkdemo2

aaa 2

bbbb 1

123 3

  

5.6.3 數值\字串處理

(1)數值處理

  •  rand():返回0和1之間一個亂數,需有個種子 srand(),沒有種子,一直輸出0.237788

演示:

1

2

3

4

5

6

7

8

9

10

11

[root@along ~]# awk 'BEGIN{print rand()}'

0.237788

[root@along ~]# awk 'BEGIN{srand(); print rand()}'

0.51692

[root@along ~]# awk 'BEGIN{srand(); print rand()}'

0.189917

---取0-50亂數

[root@along ~]# awk 'BEGIN{srand(); print int(rand()*100%50)+1}'

12

[root@along ~]# awk 'BEGIN{srand(); print int(rand()*100%50)+1}'

24

  

(2)字串處理:

  •  length([s]) :返回指定字串的長度
  •  sub(r,s,[t]) :對t 字串進行搜尋r 表示的模式匹配的內容,並將第一個匹配的內容替換爲s
  •  gsub(r,s,[t]) :對t 字串進行搜尋r 表示的模式匹配的內容,並全部替換爲s 所表示的內容
  •  plit(s,array,[r]) :以r 爲分隔符,切割字串s ,並將切割後的結果儲存至array 所表示的陣列中,第一個索引值爲1, 第二個索引值爲2,…

演示:

1

2

3

4

5

6

7

8

9

10

[root@along ~]# echo "2008:08:08 08:08:08" | awk 'sub(/:/,"-",$1)'

2008-08:08 08:08:08

[root@along ~]# echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-",$0)'

2008-08-08 08-08-08

[root@along ~]# echo "2008:08:08 08:08:08" | awk '{split($0,i,":")}END{for(n in i){print n,i[n]}}'

4 08

5 08

1 2008

2 08

3 08 08

  

5.7 awk自定義函數

(1)格式:和bash區別:定義函數()中需加參數,return返回值不是$?,是相當於echo輸出

1

2

3

4

function name ( parameter, parameter, ... ) {

    statements

    return expression

}

  

(2)演示

1

2

3

4

5

6

7

8

[root@along ~]# cat fun.awk

function max(v1,v2) {

    v1>v2?var=v1:var=v2

    return var

}

BEGIN{a=3;b=2;print max(a,b)}

[root@along ~]# awk -f fun.awk

3

  

5.8 awk中呼叫shell 命令

(1)system 命令

  空格是awk 中的字串連線符,如果system中需要使用awk中的變數可以使用空格分隔,或者說除了awk 的變數外其他一律用"" 參照 起來。

1

2

3

4

5

6

[root@along ~]# awk BEGIN'{system("hostname") }'

along

[root@along ~]# awk 'BEGIN{name="along";system("echo "name)}'  注:"echo " echo後有空格

along

[root@along ~]# awk 'BEGIN{score=100; system("echo your score is " score) }'

your score is 100

  

(2)awk 指令碼

將awk 程式寫成指令碼,直接呼叫或執行

範例:

1

2

3

4

5

6

7

8

[root@along ~]# cat f1.awk

{if($3>=1000)print $1,$3}

[root@along ~]# cat f2.awk

#!/bin/awk -f

{if($3 >= 1000)print $1,$3}

[root@along ~]# chmod +x f2.awk

[root@along ~]# ./f2.awk -F: /etc/passwd

along 1000

  

(3)向awk指令碼傳遞參數

① 格式:

1

awkfile var=value var2=value2... Inputfile

  注意 :在BEGIN 過程 中不可用。直到 首行輸入完成以後,變數纔可用 。可以通過-v  參數,讓awk 在執行BEGIN 之前得到變數的值。命令列中每一個指定的變數都需要一個-v

② 範例

1

2

3

4

5

6

[root@along ~]# cat test.awk

#!/bin/awk -f

{if($3 >=min && $3<=max)print $1,$3}

[root@along ~]# chmod +x test.awk

[root@along ~]# ./test.awk -F: min=100 max=200 /etc/passwd

systemd-network 192

 awk實戰

查詢:

 列基本查詢

[root@aly-centos7 /]# awk '{print $0}' passwd4  #$0代表整列
root x:0:0:root:/root:/bin/bash
bin x:1:1:bin:/bin:/sbin/nologin
daemon x:2:2:daemon:/sbin:/sbin/nologin
adm x:3:4:adm:/var/adm:/sbin/nologin
lp x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync x:5:0:sync:/sbin:/bin/sync
%shutdown x:6:0:shutdown:/sbin:/sbin/shutdown
$halt:x:7:0:halt:/sbin:/sbin/halt
#$mail x:8:12:mail:/var/spool/mail:/sbin/nologin
operator x:11:0:operator:/root:/sbin/nologin
1234 567890
9876 543210
[root@aly-centos7 /]# awk '{print $1}' passwd4  #$1代表第一列
root
bin
daemon
adm
lp
sync
%shutdown
$halt:x:7:0:halt:/sbin:/sbin/halt
#$mail
operator
1234
9876

 當前記憶體過濾

首先要檢視剩餘記憶體是那個欄位標記,然後標記的這一行用grep取出來,最後用awk把這一行的列取出來在加上一個可讀性語句即可
[root@aly-centos7 /]# free | grep Mem | awk '{print"當前剩餘記憶體:\n",$7}'
當前剩餘記憶體:
 1408424
[root@aly-centos7 /]#

 存取ip過濾

/var/log/secure是用於記錄存取的資訊,可以通過這個日誌來看出來是否遭受到惡意攻擊
[root@aly-centos7 /]# grep "Accepted" /var/log/secure | awk '{print $11}'
101.95.130.134
101.95.130.134
101.95.130.134
101.95.130.134
101.95.130.134
101.95.130.134
101.95.130.134
101.95.130.134
[root@aly-centos7 /]# 
通過過濾我就知道那些ip訪問了,不過存取的ip數量很多,而生產伺服器存取的ip都是固定的,一般都會有一個檔案記錄,這樣可以寫一個指令碼和你過濾的ip比對,那些沒有登記的就可以處理掉。

 統計每行有多少列(NF)

[root@aly-centos7 /]# awk '{print NF}' passwd4
2
2
2
2
2
2
2
1
2
2
2
2
[root@aly-centos7 /]# cat passwd4
root x:0:0:root:/root:/bin/bash
bin x:1:1:bin:/bin:/sbin/nologin
daemon x:2:2:daemon:/sbin:/sbin/nologin
adm x:3:4:adm:/var/adm:/sbin/nologin
lp x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync x:5:0:sync:/sbin:/bin/sync
%shutdown x:6:0:shutdown:/sbin:/sbin/shutdown
$halt:x:7:0:halt:/sbin:/sbin/halt
#$mail x:8:12:mail:/var/spool/mail:/sbin/nologin
operator x:11:0:operator:/root:/sbin/nologin
1234 567890
9876 543210
[root@aly-centos7 /]#

 分別統計多個檔案有多少行(NFR)

[root@aly-centos7 /]# awk '{print FNR}' passwd3 passwd4
1
2
3
4
5
6
7
8
9
10
1
2
3
4
5
6
7
8
9
10
11
12

 統計uid小於30的使用者有多少和大於30的餘戶有多少(判斷)

[root@aly-centos7 /]# awk -F: 'BEGIN{i=0;j=0}{if($3<=30){i++}else{j++}}END{print "<=30:"i,"\n",">=30:"j}' /etc/passwd
<=30:13
 >=30:17
[root@aly-centos7 /]#

 統計指定欄位出現的個數(while回圈)

[root@aly-centos7 /]# grep --color root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
dockerroot:x:993:991:Docker User:/var/lib/docker:/sbin/nologin
[root@aly-centos7 /]# awk -F[:/] '{i=1}{while(i<=NF){if($i~/root/){j++};i++}}END{print j}' /etc/passwd
5

 統計ip出現的次數

[root@aly-centos7 httpd]# tail -10 access_log
172.16.163.69 - - [24/Jul/2018:13:39:12 +0800] "GET / HTTP/1.0" 403 4897 "-" "ApacheBench/2.3"
172.16.163.69 - - [24/Jul/2018:13:39:12 +0800] "GET / HTTP/1.0" 403 4897 "-" "ApacheBench/2.3"
172.16.163.69 - - [24/Jul/2018:13:39:12 +0800] "GET / HTTP/1.0" 403 4897 "-" "ApacheBench/2.3"
172.16.163.69 - - [24/Jul/2018:13:39:12 +0800] "GET / HTTP/1.0" 403 4897 "-" "ApacheBench/2.3"
172.16.163.69 - - [24/Jul/2018:13:39:12 +0800] "GET / HTTP/1.0" 403 4897 "-" "ApacheBench/2.3"
172.16.163.69 - - [24/Jul/2018:13:39:12 +0800] "GET / HTTP/1.0" 403 4897 "-" "ApacheBench/2.3"
172.16.163.69 - - [24/Jul/2018:13:39:12 +0800] "GET / HTTP/1.0" 403 4897 "-" "ApacheBench/2.3"
172.16.163.69 - - [24/Jul/2018:13:39:12 +0800] "GET / HTTP/1.0" 403 4897 "-" "ApacheBench/2.3"
172.16.163.69 - - [24/Jul/2018:13:39:12 +0800] "GET / HTTP/1.0" 403 4897 "-" "ApacheBench/2.3"
172.16.163.69 - - [24/Jul/2018:13:39:12 +0800] "GET / HTTP/1.0" 403 4897 "-" "ApacheBench/2.3"
[root@aly-centos7 httpd]# awk '{ip[$1]++} END{for(i in ip){print i,ip[i]}}' /var/log/httpd/access_log
172.16.163.69 1000

 

6、grep awk sed對比

grep 主要用於搜尋某些字串;

sed,awk 用於處理文字 ;

  grep基本是以行爲單位處理文字的; 而awk可以做更細分的處理,通過指定分隔符將一行(一條記錄)劃分爲多個欄位,以欄位爲單位處理文字。awk中支援C語法,可以有分支條件判斷、回圈語句等,相當於一個小型程式語言。

  awk功能比較多是一個程式語言了。 grep功能簡單,就是一個簡單的正則表達式的匹配。 awk的功能依賴於grep。

  grep可以理解爲主要作用是在一個檔案中查詢過濾需要的內容。awk不是過濾查詢,而是文字處理工具,是把一個檔案處理成你想要的格式。

  AWK的功能是什麼?與sed和grep很相似,awk是一種樣式掃描與處理工具。但其功能卻大大強於sed和grep。awk提供了極其強大的功能:它幾乎可以完成grep和sed所能完成的全部工作,同時,它還可以可以進行樣式裝入、流控制、數學運算子、進程控制語句甚至於內建的變數和函數。它具備了一個完整的語言所應具有的幾乎所有精美特性。實際上,awk的確擁有自己的語言:awk程式設計語言,awk的三位建立者已將它正式定義爲:樣式掃描和處理語言。  使用awk的第一個理由是基於文字的樣式掃描和處理是我們經常做的工作,awk所做的工作有些象數據庫,但與數據庫不同的是,它處理的是文字檔案,這些檔案沒有專門的儲存格式,普通的人們就能編輯、閱讀、理解和處理它們。而數據庫檔案往往具有特殊的儲存格式,這使得它們必須用數據庫處理程式來處理它們。既然這種類似於數據庫的處理工作我們經常會遇到,我們就應當找到處理它們的簡便易行的方法,UNIX有很多這方面的工具,例如sed 、grep、sort以及find等等,awk是其中十分優秀的一種。 

  使用awk的第二個理由是awk是一個簡單的工具,當然這是相對於其強大的功能來說的。的確,UNIX有許多優秀的工具,例如UNIX天然的開發工具C語言及其延續C++就非常的優秀。但相對於它們來說,awk完成同樣的功能要方便和簡捷得多。這首先是因爲awk提供了適應多種需要的解決方案:從解決簡單問題的awk命令列到複雜而精巧的awk程式設計語言,這樣做的好處是,你可以不必用複雜的方法去解決本來很簡單的問題。例如,你可以用一個命令列解決簡單的問題,而C不行,即使一個再簡單的程式,C語言也必須經過編寫、編譯的全過程。其次,awk本身是解釋執行的,這就使得awk程式不必經過編譯的過程,同時,這也使得它與shell script程式能夠很好的契合。最後,awk本身較C語言簡單,雖然awk吸收了C語言很多優秀的成分,熟悉C語言會對學習awk有很大的幫助,但awk本身不須要會使用C語言——一種功能強大但需要大量時間學習才能 纔能掌握其技巧的開發工具。 

  使用awk的第三個理由是awk是一個容易獲得的工具。與C和C++語言不同,awk只有一個檔案(/bin/awk),而且幾乎每個版本的UNIX都提供各自版本的awk,你完全不必費心去想如何獲得awk。但C語言卻不是這樣,雖然C語言是UNIX天然的開發工具,但這個開發工具卻是單獨發行的,換言之,你必須爲你的UNIX版本的C語言開發工具單獨付費(當然使用D版者除外),獲得並安裝它,然後你纔可以使用它。 

  基於以上理由,再加上awk強大的功能,我們有理由說,如果你要處理與文字樣式掃描相關的工作,awk應該是你的第一選擇。在這裏有一個可遵循的一般原則:如果你用普通的shell工具或shell script有困難的話,試試awk,如果awk仍不能解決問題,則便用C語言,如果C語言仍然失敗,則移至C++。 

  sed是一個非互動性文字流編輯器。它編輯檔案或標準輸入導出的文字拷貝。sed編輯器按照一次處理 一行的方式來處理檔案(或者輸入)並把輸出送到螢幕上。你可以在vi和ex/ed編輯器裡識別他的命令。sed把當前正在處理的行儲存在一個臨時快取裡,這個快取叫做模式空間。一但sed完成了對模式空間裡的行的處理(即對該行執行sed命令),就把模式空間的行送到螢幕上(除非該命令要刪除該行活禁止列印)。處理完該行之後,從模式空間裡刪除它,然後把下一行讀入模式空間,進行處理,並顯示。當輸入檔案的最後一行處理完後,sed終止。通過把每一行存在一個臨時快取裡並編輯該行,初始檔案不會被修改或被破壞。