awk
本章內容:
-
awk介紹
-
awk基本用法
-
awk變量
-
awk格式化
-
awk操作符
-
awk條件判斷
-
awk循環
-
awk數組
-
awk函數
-
調用系統命令
1.awk介紹
★ Linux 文本處理工具三劍客:grep、sed、awk。其中grep是一種文本過濾工具;sed是文本行編輯器,而awk是一種報表生成器,就是對文件進行格式化處理的,但這里的格式化不是文件系統的格式化,而是對文件內容進行各種“排版”,進而格式化顯示;
★ 在Linux之上我們使用的是GNU awk 簡稱gawk,并且gawk就是awk的鏈接文件,因此系統上使用的awk和gawk是一樣的。我們通過man gawk可以獲得gawk的相關功能說明—gawk-pattern scanning and processing language(模式掃描及處理語言),gawk是一種過程式編程語言。gawk還支持條件判斷、數組、循環等編程語言中所有可以使用的功能,因此還可以把gawk稱為一種腳本語言解釋器。
1)介紹如下:
★ 文本處理三工具:grep、sed、awk
grep,egrep,fgrep:文本過濾工具:partten
sed:行編輯器;模式空間、保持空間
awk:報告生成器,格式化文本輸出;
★ AWK
Aho, Weinberger, Kernighan,報告生成器,格式化文本輸出;
有多種版本:New awk(nawk),GNU awk(gawk);
gawk –模式掃描和處理語言;
[root@centos7 ~]# which awk /usr/bin/awk [root@centos7 ~]# ll /usr/bin/awk lrwxrwxrwx. 1 root root 4 Jul 25 23:58 /usr/bin/awk -> gawk★ 基本用法:
awk[options] ‘program’ var=value file…
awk[options] -f programfilevar=value file…
awk[options] 'BEGIN{ action;… } pattern{ action;… } END{ action;… }' file …
awk程序通常由:BEGIN語句塊、能夠使用模式匹配的通用語句塊、END語句塊,共3部分組成
用法說明
1)用法格式,選項
★基本格式:awk [options] 'program' file…
·program:PATTERN{ACTION STATEMENT;..},通常是在單引號和雙引號中;
·program:編程語言;
·PARTTERN:
模式;部分決定動作語句何時觸發及觸發事件(BEGIN,END)
·ACTION STATEMENT:
動作語句,可以由多個語句組成,各語句之間使用分號分隔:如print,printf
★options(選項):
-F:指明輸入時用到的字段分隔符;
-v var=value: 自定義變量
★分割符、域和記錄
·awk執行時,由分隔符分隔的字段(域);標記$1,$2..$n稱為域標識。$0為所有域,注意:和shell中變量$符含義不同
·文件的每一行稱為記錄
·省略action,則默認執行print $0 的操作。
2)awk工作原理
★ 原理:
awk在處理文本時也是一次讀取一行文本,然后根據輸入分隔符(默認為空格字符)進行切片,切成n個片段,然后將每一片都賦予awk內部的一個變量當中進行保存,這些變量名為$1,$2,$3…等等一直到最后一個,awk就可以對這些片段進行單獨處理,比如顯示某一段,特定段,甚至可以對某些片段進行額外的的加工處理,比如計數、運算等。
★ 具體工作原理如下:
·第一步:執行BEGIN{action;… }語句塊中的語句;
·第二步:從文件或標準輸入(stdin)讀取一行,然后執行pattern{ action;… }語句塊,它逐行掃描文件,從第一行到最后一行重復這個過程,直到文件全部被讀取完畢。
·第三步:當讀至輸入流末尾時,執行END{action;…}語句塊
·BEGIN語句塊在awk開始從輸入流中讀取行之前被執行,這是一個可選的語句塊,比如變量初始化、打印輸出表格的表頭等語句通??梢詫懺贐EGIN語句塊中
·END語句塊在awk從輸入流中讀取完所有的行之后即被執行,比如打印所有行的分析結果這類信息匯總都是在END語句塊中完成,它也是一個可選語句塊
·pattern語句塊中的通用命令是最重要的部分,也是可選的。如果沒有提供pattern語句塊,則默認執行{ print },即打印每一個讀取到的行,awk讀取的每一行都會執行該語句塊。
舉例:
[root@centos7 ~]# tail -5 /etc/fstab # 取 /etc/fstab 的后五行 UUID=5de91e7f-4334-4646-8bcf-7e8df5969f74 / xfs defaults 0 0 UUID=abad3f46-4294-40b0-9d48-78c7e87cbfbf /boot xfs defaults 0 0 UUID=01aef744-48b5-4346-ab7d-33150e05f3c7 /usr xfs defaults 0 0 UUID=9765d553-e77b-48db-a4ff-502e43833384 swap swap defaults 0 0 UUID=a42aca7a-085a-43c2-a22c-4f4aa6a22574 /testdir ext4 acl 0 0 [root@centos7 ~]# tail -5 /etc/fstab |awk '{print $2,$3}' # 對讀進來的每一行都執行打印第2和第3片段 / xfs /boot xfs /usr xfs swap swap /testdir ext4 [root@centos7 ~]# tail -5 /etc/fstab |awk '{print "hello",$2,$3}' hello / xfs hello /boot xfs hello /usr xfs hello swap swap hello /testdir ext4
輸出命令:print
print格式:print item1, item2, …
要點:
(1) 逗號分隔符;
(2) 輸出的各item可以是字符串,也可以是數值、當前記錄的字段、變量或awk的表達式;
(3) 如省略item,相當于print $0
演示:
[root@centos7 ~]# awk '{print "hello,awk"}' # 不管輸入什么都只打印定義好的 asdas hello,awk asfas hello,awk dddd hello,awk [root@centos7 ~]# awk -F: '{print}' /etc/passwd # 把/etc/passwd的每一行都打印一遍 root:x:0:0:tcpdump,,62985600:/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 [root@centos7 ~]# awk -F: '{print "tao"}' /etc/passwd # /etc/passwd 的每一行輸入進去之后都打印成 tao tao tao tao tao [root@centos7 ~]# awk -F: '{print $1}' /etc/passwd # 以:為分隔符,打印每一行的第一個片段 root bin daemon adm lp [root@centos7 ~]# awk -F: '{print $1"\t"$3}' /etc/passwd # 也可以用其他分隔符,但一定要加雙引號。 root 0 bin 1 daemon 2 adm 3 lp 4 sync 5
awk變量
內置和自定義變量
★內置變量
·FS:輸入字段分隔符,默認為空白字符
awk -v FS=':' '{print $1,$3,$7}’ /etc/passwd
awk–F: '{print $1,$3,$7}’ /etc/passwd
·OFS:輸出字段分隔符,默認為空白字符
awk-v FS=‘:’ -v OFS=‘:’ '{print $1,$3,$7}’ /etc/passwd
·RS:輸入記錄分隔符,指定輸入時的換行符,原換行符仍有效
awk -v RS=' ' ‘{print }’ /etc/passwd
·ORS:輸出記錄分隔符,輸出時用指定符號代替換行符
awk-v RS=' ' -v ORS='###'‘{print }’ /etc/passwd
·NF:字段數量
awk -F:‘{print NF}’ /etc/fstab, 引用內置變量不用$
awk -F: '{print $(NF-1)}' /etc/passwd
·NR:行號
awk '{print NR}' /etc/fstab; awk END'{print NR}' /etc/fstab
·FNR:各文件分別計數,行號
awk '{print FNR}' /etc/fstab /etc/inittab
·FILENAME:當前文件名
awk '{print FILENAME}’ /etc/fstab
·ARGC:命令行參數的個數
awk '{print ARGC}’ /etc/fstab /etc/inittab
awk ‘BEGIN {print ARGC}’ /etc/fstab /etc/inittab
·ARGV:數組,保存的是命令行所給定的各參數
awk ‘BEGIN {print ARGV[0]}’ /etc/fstab /etc/inittab
awk ‘BEGIN {print ARGV[1]}’ /etc/fstab /etc/inittab
★自定義變量
·-v var=value
變量名區分字符大小寫
·在program中直接定義
awk -v test='hello gawk' '{print test}' /etc/fstab
awk -v test='hello gawk' 'BEGIN{print test}'
awk'BEGIN{test="hello,gawk";print test}'
內置變量演示:
[root@centos7 ~]# awk -F: '{print $1,$3,$7}' /etc/passwd # 指明以“:”作為輸入字段分隔符,如果不指明的話以空白當做分隔符 root 0 /bin/bash bin 1 /sbin/nologin daemon 2 /sbin/nologin adm 3 /sbin/nologin lp 4 /sbin/nologin [root@centos7 ~]# awk -F: -v OFS='=>' '{print $1,$3,$7}' /etc/passwd # 指明輸入,輸出字段分隔符 root=>0=>/bin/bash bin=>1=>/sbin/nologin daemon=>2=>/sbin/nologin adm=>3=>/sbin/nologin lp=>4=>/sbin/nologin sync=>5=>/bin/sync [root@centos7 ~]# awk -F: -v ORS='###' '{print }' /etc/passwd # 指明輸出是的換行符 root:x:0:0:tcpdump,,62985600:/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 [root@centos7 ~]# awk -F: '{print NF}' /etc/passwd # 以:為分隔符,打印每一行的字段數量 7 7 7 7 7 7 7 7 7 [root@centos7 ~]# awk -F: '{print $NF}' /etc/passwd # 這時,$NF=$7,因為NF為內之變量替換為7 /bin/bash /sbin/nologin /sbin/nologin /sbin/nologin /sbin/nologin [root@centos7 ~]# awk '{print NR }' /etc/passwd # 顯示行號 1 2 3 4 5 6 7 [root@centos7 ~]# awk '{print FNR }' /etc/fstab /etc/issue 1 # 如果后面跟多個文件的話,要想顯示每個文件的行數,變量為FNR,如果不加F,則行號累加 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 [root@centos7 ~]# awk END'{print NR }' /etc/fstab # 顯示最后一行的行號 13 [root@centos7 ~]# awk END'{print FNR }' /etc/fstab /etc/issue 6 [root@centos7 ~]# awk '{print FILENAME}' /etc/fstab # 顯示當前文件名 /etc/fstab /etc/fstab /etc/fstab /etc/fstab /etc/fstab /etc/fstab /etc/fstab /etc/fstab [root@centos7 ~]# awk '{print ARGC}' /etc/fstab /etc/inittab # 命令行參數個數,但會輸入的每行都會顯示一遍 3 3 3 3 3 [root@centos7 ~]# awk 'BEGIN {print ARGC}' /etc/fstab /etc/inittab 3 # 加上BEGIN 只顯示一次命令行參數個數 [root@centos7 ~]# awk 'BEGIN {print ARGV[0]}' /etc/fstab /etc/inittab awk # 數組,顯示的是命令行的第幾個參數 [root@centos7 ~]# awk 'BEGIN {print ARGV[1]}' /etc/fstab /etc/inittab /etc/fstab [root@centos7 ~]# awk 'BEGIN {print ARGV[2]}' /etc/fstab /etc/inittab /etc/inittab
自定義變量演示:
[root@centos7 ~]# awk -v test='hello gawk' '{print test}' /etc/fstab hello gawk hello gawk hello gawk hello gawk hello gawk hello gawk hello gawk hello gawk hello gawk hello gawk hello gawk hello gawk hello gawk [root@centos7 ~]# awk -v test='hello gawk' 'BEGIN{print test}' /etc/fstab hello gawk [root@centos7 ~]# awk 'BEGIN{test="hello,gawk";print test}' hello,gawk
輸出命令:printf
★ 格式化輸出:printf“FORMAT”, item1, item2, …
(1) 必須指定FORMAT;
(2) 不會自動換行,需要顯式給出換行控制符,\n;
(3) FORMAT中需要分別為后面每個item指定格式符;
★ 格式符:與item一一對應
%c:顯示字符的ASCII碼;
%d, %i:顯示十進制整數;
%e, %E:科學計數法數值顯示;
%f:顯示為浮點數;
%g, %G:以科學計數法或浮點形式顯示數值;
%s:顯示字符串;
%u:無符號整數;
%%: 顯示%自身;
★ 修飾符:
#[.#]:第一個數字控制顯示的寬度;第二個#表示小數點后精度,%3.1f
-: 左對齊(默認右對齊)%-15s
+:顯示數值的正負符號%+d
命令演示:
[root@centos7 ~]# awk -F: '{printf "%s",$1}' /etc/passwd # 顯示字符串,默認不自動換行 rootbindaemonadmlpsyncshutdownhaltmailoperatorgamesftpnobodyavahi-autoipdsystemd-bus-proxysystemd-networkdbuspolkitdabrtcolordlibstoragemgmtsetroubleshootrpcrtkitchronytssgeoclueusbmuxdmysqlpulsegdmrpcuserpostfixsshdntpapachetao [root@centos7 ~]# awk -F: '{printf "%s\n",$1}' /etc/passwd # 添加自動換行符 root bin daemon adm lp sync shutdown halt [root@centos7 ~]# awk -F: '{printf "Username: %s\n",$1}' /etc/passwd Username: root # 可以添加字符串 Username: bin Username: daemon Username: adm Username: lp Username: sync Username: shutdown [root@centos7 ~]# awk -F: '{printf "Username:%s UID:%d\n",$1,$3}' /etc/passwd Username:root UID:0 # 格式和條目片段是對應的,每個片段會套在其對應的格式上 Username:bin UID:1 Username:daemon UID:2 Username:adm UID:3 Username:lp UID:4 Username:sync UID:5 Username:shutdown UID:6 [root@centos7 ~]# awk -F: '{printf "Username:%15s UID:%d\n",$1,$3}' /etc/passwd Username: root UID:0 # 添加修飾符,顯示寬度為15字符,默認為右對齊 Username: bin UID:1 Username: daemon UID:2 Username: adm UID:3 Username: lp UID:4 Username: sync UID:5 Username: shutdown UID:6 Username: halt UID:7 [root@centos7 ~]# awk -F: '{printf "Username:%-15s UID:%d\n",$1,$3}' /etc/passwd Username:root UID:0 # 左對齊顯示 Username:bin UID:1 Username:daemon UID:2 Username:adm UID:3 Username:lp UID:4 Username:sync UID:5 Username:shutdown UID:6
操作符
★ 算數操作符:
x+y, x-y, x*y, x/y, x^y(x的y次方), x%y
-x: 轉換為負數;
+x: 轉換為數值;
★ 字符串操作符:沒有符號的操作符,字符串連接;
★ 賦值操作符:
=, +=, -=, *=, /=, %=, ^=
++, —
★ 比較操作符:
>, >=, <, <=, !=, ==
★ 模式匹配符:
~:左邊是否和右邊匹配包含
!~:是否不匹配
cat /etc/passwd |awk'$0 ~ /root/' |wc -l
cat /etc/passwd |awk'$0 !~ /root/' |wc -l
★ 邏輯操作符:&&,||,!
示例:
awk–F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd
awk -F: '$3 ==0 || $3>=1000 {print $1}' /etc/passwd
awk -F: ‘!($3==0){print $1}' /etc/passwd
awk -F: '!($3>=500) {print $3}}' /etc/passwd
★ 函數調用:
function_name(argu1, argu2, …)
★ 條件表達式:
selector?if-true-expression:if-false-expression
命令演示:
[root@centos7 ~]# awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf"%15s:%-s\n",$1,usertype}' /etc/passwd root:Sysadmin or SysUser # 顯示用戶的UID如果大等于1000則為普通用戶,否則為管理員或系統用戶,并定義格式輸出 bin:Sysadmin or SysUser daemon:Sysadmin or SysUser adm:Sysadmin or SysUser lp:Sysadmin or SysUser sync:Sysadmin or SysUser shutdown:Sysadmin or SysUser halt:Sysadmin or SysUser mail:Sysadmin or SysUser operator:Sysadmin or SysUser games:Sysadmin or SysUser ftp:Sysadmin or SysUser nobody:Sysadmin or SysUser avahi-autoipd:Sysadmin or SysUser systemd-bus-proxy:Sysadmin or SysUser systemd-network:Sysadmin or SysUser dbus:Sysadmin or SysUser polkitd:Sysadmin or SysUser abrt:Sysadmin or SysUser colord:Sysadmin or SysUser libstoragemgmt:Sysadmin or SysUser setroubleshoot:Sysadmin or SysUser rpc:Sysadmin or SysUser rtkit:Sysadmin or SysUser chrony:Sysadmin or SysUser tss:Sysadmin or SysUser geoclue:Sysadmin or SysUser usbmuxd:Sysadmin or SysUser mysql:Sysadmin or SysUser pulse:Sysadmin or SysUser gdm:Sysadmin or SysUser rpcuser:Sysadmin or SysUser postfix:Sysadmin or SysUser sshd:Sysadmin or SysUser ntp:Sysadmin or SysUser apache:Sysadmin or SysUser tao:Common User
PATTERN
PATTERN:根據pattern條件,過濾匹配的行,再做處理
★ 如果未指定:空模式,匹配每一行
★ /regular expression/:僅處理能夠模式匹配到的行,需要用/ /括起來;
awk'/^UUID/{print $1}' /etc/fstab
awk'!/^UUID/{print $1}' /etc/fstab
★ relational expression: 關系表達式;
結果有“真”有“假”;結果為“真”才會被處理;
真:結果為非0值,非空字符串;
假:結果為空字符串;
★ line ranges:行范圍
startline,endline:/pat1/,/pat2/不支持直接給出數字格式
awk -F: '/^root/,/^nobody/{print $1}' /etc/passwd
awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd
★ BEGIN/END 模式
BEGIN{}: 僅在開始處理文件中的文本之前執行一次
END{}:僅在文本處理完成之后執行一次
命令演示:
[root@centos7 ~]# awk '/^UUID/{print $1}' /etc/fstab # 處理匹配到的模式 UUID=90880561-dca2-447b-a935-4c47e1bd03d8 UUID=219cc6c3-bd54-4bac-a47f-b498c491107f UUID=409f2fa0-f642-4cc2-9ed7-b20bda111d8d UUID=af279379-acbd-47f5-a814-870666bdd6d1
[root@centos7 ~]# awk '!/^UUID/{print $1}' /etc/fstab # 對匹配到的模式取反 # # # # # # #
[root@centos7 ~]# awk -F: '$3>=1000{print $1,$3}' /etc/passwd nfsnobody 65534 # 關系表達式,也可以成為比較表達式,條件為真,才會被處理。題目表示,如果UID大于等于1000,則打印用戶名和UID tao 1000
[root@centos7 ~]# awk -F: '$NF=="/bin/bash"{print $1,$3}' /etc/passwd root 0 # 表示最后一個片段等于/bin/bash,然后符合的打印 用戶名和UID tao 1000 [root@centos7 ~]# awk -F: '$NF~/bash/ {print $1,$NF}' /etc/passwd root /bin/bash # 表示左邊的值能夠被右邊的模式所匹配, tao /bin/bash
[root@centos7 ~]# seq 10 |awk 'i=!i' 1 3 5 7 9
[root@centos7 ~]# awk -F: '/^root/,/^nobody/{print $1}' /etc/passwd root # 表示第一次被/^root/模式匹配到的行開始,到第一次被/^nobody/模式匹配到的行結束 bin daemon adm lp sync shutdown halt mail operator games ftp nobody [root@centos7 ~]# awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd bin # 表示第二行到第十行,打印用戶名 daemon adm lp sync shutdown halt mail operator
[root@centos7 ~]# awk -F: 'BEGIN{print " username uid \n----------------------"}' username uid ---------------------- # 打印表頭 [root@centos7 ~]# awk -F: 'BEGIN{print " username uid \n--------------------------"}{printf "%18s %3d\n",$1,$3}' /etc/passwd username uid -------------------------- root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6
[root@centos7 ~]# awk -F: 'BEGIN{print " username uid \n--------------------------"}{print $1,$3}END{print "=======================\n END"}' /etc/passwd username uid -------------------------- root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 dbus 81 polkitd 997 abrt 173 colord 996 tcpdump 72 tao 1000 ======================= END
常用的action
Expressions: 算術,比較表達式等
Control statements: 控制語句 if, while等
Compound statements: 組合語句
input statements: 輸入語句
output statements: 輸出語句 print等
awk控制語句
{ statements;… } 組合語句
if(condition) {statements;…}
if(condition) {statements;…} else {statements;…}
while(conditon) {statments;…}
do {statements;…} while(condition)
for(expr1;expr2;expr3) {statements;…}
break
continue
delete array[index]
delete array
exit
1)awk控制語句:if-else
★語法:
if(condition) statement [else statement]
if(condition1){statement1} else if(condition2)
{statement 2}else{statement3}
★使用場景:對awk取得的整行或某個字段做條件判斷
命令演示:
[root@centos7 ~]# awk -F: '{if($3>=1000) print $1,$3}' /etc/passwd # 單分支語句 nfsnobody 65534 tao 1000 [root@centos7 ~]# 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 root or Sysuser: daemon root or Sysuser: adm root or Sysuser: lp root or Sysuser: sync root or Sysuser: shutdown root or Sysuser: halt root or Sysuser: mail root or Sysuser: operator root or Sysuser: games root or Sysuser: ftp root or Sysuser: nobody root or Sysuser: avahi-autoipd root or Sysuser: systemd-bus-proxy root or Sysuser: systemd-network root or Sysuser: dbus root or Sysuser: polkitd root or Sysuser: abrt root or Sysuser: colord root or Sysuser: libstoragemgmt root or Sysuser: setroubleshoot root or Sysuser: rpc root or Sysuser: rtkit root or Sysuser: chrony root or Sysuser: tss root or Sysuser: geoclue root or Sysuser: usbmuxd root or Sysuser: mysql root or Sysuser: pulse root or Sysuser: gdm root or Sysuser: rpcuser Common user: nfsnobody root or Sysuser: postfix root or Sysuser: sshd root or Sysuser: ntp root or Sysuser: tcpdump Common user: tao
[root@centos7 ~]# awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd root # 對某個字段做條件判斷 tao
[root@centos7 ~]# awk '{if(NF>5) print $0}' /etc/fstab # 如果字段大于5,就打印 # Created by anaconda on Tue Aug 30 09:45:37 2016 # Accessible filesystems, by reference, are maintained under '/dev/disk' # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info UUID=90880561-dca2-447b-a935-4c47e1bd03d8 / xfs defaults 0 0 UUID=219cc6c3-bd54-4bac-a47f-b498c491107f /boot xfs defaults 0 0 UUID=409f2fa0-f642-4cc2-9ed7-b20bda111d8d /usr xfs defaults 0 0 UUID=af279379-acbd-47f5-a814-870666bdd6d1 swap swap defaults 0 0
取磁盤利用率:
[root@centos7 ~]# df -h |awk -F[%] '{print $1}' # 以%為分隔符,取第一字段 Filesystem Size Used Avail Use /dev/sda2 40G 915M 40G 3 devtmpfs 475M 0 475M 0 tmpfs 489M 0 489M 0 tmpfs 489M 6.7M 483M 2 tmpfs 489M 0 489M 0 /dev/sda3 20G 2.8G 18G 14 /dev/sda1 485M 138M 348M 29 tmpfs 98M 0 98M 0 [root@centos7 ~]# df -h |awk -F[%] '{print $1}' |awk '{print $NF}' Use # 再取最后一個字段 3 0 0 2 0 14 29 0 [root@centos7 ~]# df -h |awk -F[%] '/^\/dev/{print $1}' |awk '{print $1,$NF}' /dev/sda2 3 # 模式匹配,匹配 以/dev開頭的行,注意這里要對/ 轉義,模式匹配一定要寫在 “/ /”中 /dev/sda3 14 /dev/sda1 29 [root@centos7 ~]# df -h |awk -F[%] '/^\/dev/{print $1}' |awk '{if($NF>=20) print $1}' /dev/sda1 # 如果利用率大于等于20,就打印第一字段
2)awk控制語句:while循環
★ 語法:while(condition) statement
★ 條件“真”,進入循環;條件“假”,退出循環;
★ 使用場景:
對一行內的多個字段逐一類似處理時使用;
對數組中的各元素逐一處理時使用;
[root@centos7 ~]# awk '/[[:space:]]*linux16/{print}' /etc/grub2.cfg # 取文件模式所匹配的行 linux16 /vmlinuz-3.10.0-327.el7.x86_64 root=UUID=90880561-dca2-447b-a935-4c47e1bd03d8 ro rhgb quiet LANG=en_US.UTF-8 linux16 /vmlinuz-0-rescue-a7ea085c1be64e7386b85deb2bfc1f18 root=UUID=90880561-dca2-447b-a935-4c47e1bd03d8 ro rhgb quiet [root@centos7 ~]# awk '/[[:space:]]*linux16/{print NF}' /etc/grub2.cfg 7 # 所匹配行的字段數量 6 [root@centos7 ~]# awk '/[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i);i++ }}' /etc/grub2.cfg # 對每一行字段中包含的字符長度做統計。 這里用到了while循環,當i小于等于字段數量,是就執行打印這一字段,及字段長短,并且執行i++,注意循環體用{}括起來 linux16 7 /vmlinuz-3.10.0-327.el7.x86_64 30 root=UUID=90880561-dca2-447b-a935-4c47e1bd03d8 46 ro 2 rhgb 4 quiet 5 LANG=en_US.UTF-8 16 linux16 7 /vmlinuz-0-rescue-a7ea085c1be64e7386b85deb2bfc1f18 50 root=UUID=90880561-dca2-447b-a935-4c47e1bd03d8 46 ro 2 rhgb 4 quiet 5
# 在上題的基礎之上嵌套了一個if語句,表示如果字符長度大于7才打印,注意這里的{}表示的意義,最外面一層是整個的處理語句,倒數第二層表示循環體,最里面的表示if語句的執行動作,i++是while語句的,用分號分開 [root@centos7 ~]# awk '/[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i)};i++}}' /etc/grub2.cfg linux16 7 /vmlinuz-3.10.0-327.el7.x86_64 30 root=UUID=90880561-dca2-447b-a935-4c47e1bd03d8 46 LANG=en_US.UTF-8 16 linux16 7 /vmlinuz-0-rescue-a7ea085c1be64e7386b85deb2bfc1f18 50 root=UUID=90880561-dca2-447b-a935-4c47e1bd03d8 46
3)awk控制語句:do-while循環
★語法:do statement while(condition)
★意義:無論真假,至少執行一次循環體
命令演示:
[root@centos7 ~]# awk 'BEGIN{ total=0;i=0;do{ total+=i;i++;}while(i<=100);print total}' 5050
4)awk控制語句:for循環
★語法:for(expr1;expr2;expr3) statement
for(variable assignment;condition;iterationprocess) {for-body}
★特殊用法:能夠遍歷數組中的元素;
語法:for(varin array) {for-body}
[root@centos7 ~]# awk '/[[:space:]]*linux16/ {for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg linux16 7 /vmlinuz-3.10.0-327.el7.x86_64 30 root=UUID=90880561-dca2-447b-a935-4c47e1bd03d8 46 ro 2 rhgb 4 quiet 5 LANG=en_US.UTF-8 16 linux16 7 /vmlinuz-0-rescue-a7ea085c1be64e7386b85deb2bfc1f18 50 root=UUID=90880561-dca2-447b-a935-4c47e1bd03d8 46 ro 2 rhgb 4 quiet 5
[root@centos7 ~]# awk '/[[:space:]]*linux16/ {for(i=1;i<=NF;i++) {if(length($i)>=7) print $i,length($i)}}' /etc/grub2.cfg linux16 7 /vmlinuz-3.10.0-327.el7.x86_64 30 root=UUID=90880561-dca2-447b-a935-4c47e1bd03d8 46 LANG=en_US.UTF-8 16 linux16 7 /vmlinuz-0-rescue-a7ea085c1be64e7386b85deb2bfc1f18 50 root=UUID=90880561-dca2-447b-a935-4c47e1bd03d8 46
5)awk控制語句:switch語句
★語法:switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; …; default: statement}
6)break和continue
★break [n]
continue [n]
7)next
★提前結束對本行處理而直接進入下一行處理(awk自身循環)
命令演示:
[root@centos7 ~]# awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd root 0 # 表示用戶的ID號如果不為偶數,就提前終止這一行,直接進入下一行處理。 daemon 2 lp 4 shutdown 6 mail 8 games 12 ftp 14 avahi-autoipd 170 systemd-network 998 colord 996 setroubleshoot 994 rpc 32 rtkit 172 geoclue 992 gdm 42 nfsnobody 65534 sshd 74 ntp 38 tcpdump 72 tao 1000 [root@centos7 ~]# awk -F: '{if($3%2==0) print $1,$3}' /etc/passwd root 0 # 和上面表示的結果是相同的,但方法和意義不同 daemon 2 lp 4 shutdown 6 mail 8 games 12 ftp 14 avahi-autoipd 170 systemd-network 998 colord 996 setroubleshoot 994 rpc 32 rtkit 172 geoclue 992 gdm 42 nfsnobody 65534 sshd 74 ntp 38 tcpdump 72 tao 1000
awk數組
★關聯數組:array[index-expression]
★index-expression:
(1) 可使用任意字符串;字符串要使用雙引號括起來
(2) 如果某數組元素事先不存在,在引用時,awk會自動創建此元素,并將其值初始化為“空串”
★若要判斷數組中是否存在某元素,要使用“index in array”格式進行遍歷
★若要遍歷數組中的每個元素,要使用for循環
for(varin array) {for-body}
注意:var會遍歷array的每個索引
示例:
awk'{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log
[root@centos7 ~]# awk 'BEGIN{weekdays["mon"]="Monday";weekday["tue"]="Tuesday";print weekdays["mon"]}' Monday [root@centos7 ~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["tue"]}' Tuesday
遍歷數組中的每個元素:for
[root@centos7 ~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}' Tuesday Monday
[root@centos7 ~]# netstat -tan |awk '/^tcp\>/{print}' tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN tcp 0 0 127.0.0.1:6010 0.0.0.0:* LISTEN tcp 0 52 10.1.249.203:22 10.1.250.25:51498 ESTABLISHED # 本題為第二種情況,數組元素事先不存在,在引用時,awk會自動創建此元素,其初始值為“空串”也就是0。題目中,$NF變量作為數組的索引下標,其個數,出現一次就自加,自加的結果為數組元素 的值;定義的for循環中的變量i為數組中的索引下標,state[i]才是數組中元素的值,最后打印數 組中的索引下標和數組元素。 [root@centos7 ~]# netstat -tan |awk '/^tcp\>/{state[$NF]++}END{for(i in state) {print i,state[i]}}' LISTEN 4 ESTABLISHED 1
練習:
1.統計/etc/fstab文件中每個文件系統類型出現的次數
[root@centos7 ~]# awk '/^UUID/{print}' /etc/fstab UUID=90880561-dca2-447b-a935-4c47e1bd03d8 / xfs defaults 0 0 UUID=219cc6c3-bd54-4bac-a47f-b498c491107f /boot xfs defaults 0 0 UUID=409f2fa0-f642-4cc2-9ed7-b20bda111d8d /usr xfs defaults 0 0 UUID=af279379-acbd-47f5-a814-870666bdd6d1 swap swap defaults 0 0 [root@centos7 ~]# awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab swap 1 xfs 3
2.統計指定文件中每個單詞出現的次數(行內字段遍歷)
# 因為是對整個文件做遍歷,所以不用過濾行,然后遍歷每一行中單詞(默認空格分隔為一個單詞)出現的個數,最后打印索引下標和元素個數 [root@centos7 ~]# awk '{for(i=1;i<=NF;i++) {count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab Tue 1 man 1 and/or 1 maintained 1 xfs 3 Accessible 1 # 7 30 1 are 1 defaults 4 UUID=219cc6c3-bd54-4bac-a47f-b498c491107f 1 blkid(8) 1 / 1
awk函數
★數值處理:
rand():返回0和1之間一個隨機數
★字符串處理:
length([s]):返回指定字符串的長度
sub(r,s,[t]):在t字符串搜索能夠被r表示的模式所匹配的內容,并將第一個匹配的內容替換為s;
gsub(r,s,[t]):對t字符串進行搜索r表示的模式匹配的內容,并全部替換為s所表示的內容
split(s,array,[r]):以r為分隔符切割字符s,并將切割后的結果保存至array所表示的數組中
示例:
# 數值處理,rand()示例 [root@centos7 ~]# awk 'BEGIN{print rand()}' 0.237788 [root@centos7 ~]# awk 'BEGIN{print rand()}' 0.237788 [root@centos7 ~]# awk 'BEGIN{print rand()}' 0.237788 [root@centos7 ~]# awk 'BEGIN{print rand()}' 0.237788
[root@centos7 ~]# awk 'BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100) }' 51 40 86 36 75 30 14 7 58 96
# 把第一個字段(2008:08:08)中第一次查找到的 :替換為“”空, [root@centos7 ~]# echo "2008:08:08 08:08:08" | awk 'sub(/:/,"",$1)' 200808:08 08:08:08 #把第一個字段中所有的 :替換為空 [root@centos7 ~]# echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"",$1)' 20080808 08:08:08
[root@centos7 ~]# netstat -tan | awk '/^tcp\>/{split($5,ip,":");print ip[1]}' 0.0.0.0 0.0.0.0 0.0.0.0 0.0.0.0 10.1.250.25 # 相當于嵌套了一個數組,對ip[1]數組中的元素做統計 [root@centos7 ~]# netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) print i,count[i]}' 0.0.0.0 4 10.1.250.25 1
原創文章,作者:zhumengxiaotao,如若轉載,請注明出處:http://www.www58058.com/48986
總結的很棒,對awk命令的使用介紹的很詳細哦。贊一個