awk筆記整理

awk介紹

awk:報告生成器,格式化文本輸出。有多種版本:New awk(nawk),GNU awk(gawk)。CentOS中使用的是gawk
gawk:模式掃描和處理語言

awk基本用法

awk程序可由:BEGIN語句塊、能夠使用模式匹配的通用語句塊(program)、END語句塊,共3部分組成 pragram通常是被放在單引號中
常用選項:
-F "分隔符" 指明輸入時用到的字段分隔符,如果不指定分隔符,默認以空格分隔
-V var=value 變量賦值

awk變量

awk變量有內置和自定義變量
常用內置變量:
變量名 | 作用
$0 | 表示一整行 |
$1-$n | 表示第一個字段到第n個字段 |
FS | 輸入字段分隔符,默認爲空白字符 |
OFS | 輸出字段分隔符,默認爲空白字符 |
RS | 輸入記錄分隔符,指定輸入時的換行符 |
ORS | 輸出記錄分隔符,指定輸出時的換行符 |
NF | 字段數量 |
NR | 記錄號 |
FNR | 各文件分別記數,記錄號 |
FILENAME | 當前處理文件的文件名 |
ARGC|命令行參數的個數,awk算第一個參數,中間語句不算參數 |
ARGV|數組,保存的是命令午所給定的各參數|

[root@CentOS7 data]#awk 'BEGIN{print ARGV[0] }' /etc/fstab
awk
[root@CentOS7 data]#awk 'BEGIN{print ARGV[1] }' /etc/fstab
/etc/fstab

自定義變量(區分字符大小寫)

[root@CentOS7 data]#awk -v test='hello gawk' '{print test}' /etc/fstab
hello gawk
.
.
.
hello gawk
[root@CentOS7 data]#awk -v test='hello gawk' 'BEGIN{print test}'
hello gawk
[root@CentOS7 data]#awk 'BEGIN{test="hello,gawk";print test}'
hello,gawk

awk格式化

printf命令
格式化輸出:print "FORMAT",item1,item2...

1、必須指定FORMAT
2、不會自動換行,需要顯式給出換行控制符,\n
3、FORMAT中需要分別爲後面第個item指定格式符
格式符:與item一一對應
%c:顯示字符的ASCII碼
%d,%i:顯示十進制整數
%e,%E:顯示科學計數法數值
%f:顯示爲浮點數
%g,%G以科學計數法或浮點形式顯示數值
%s:顯示字符串
%u:無符號整數
%%:顯示%

修飾符
#[.#] 第一個數字控制顯示的寬度;第二個#表示小數點後數度,%3.1f表示顯示到小數點後一位

awk操作符

算術操作符

+、-、*、/、^、% 加減乘除乘取餘
-x:轉換爲負數
+x:將字符串轉換爲數值

字符串操作符:沒有符號的操作符,字符串連接
賦值操作符

=,+=,-=,*=,/=,%=,^=,++,--

比較操作符

==,!=,>,>=,<,<=

模式匹配符:

~:左邊是否和右邊匹配,包含
!~: 是否不匹配

邏輯操作符:與&&,或||,非!
條件表達式(三目表達式)
selector?if-true-expression:if-false-expression
如果selector 爲真,執行if-true部分,爲假,執行if-false部分

awk條件判斷

根據模式(pattern)條件,過濾匹配的行,再做處理

如果未指定:空模式,匹配第一行

/regular expression/ :僅處理能夠與模式相匹配的行,需要用//括起來

[root@CentOS7 data]#awk '/^UUID/{print $1}' /etc/fstab
UUID=95730fd4-d3a2-4af9-8311-46422db2ed23
UUID=8ea0b7b5-109d-43b7-bd1a-f18c5f4ae5de
UUID=f6d8e5da-09bf-480a-9089-a83d8cb674c5
UUID=74df8071-4517-4645-872e-976e8a5514e4

表示只顯示以UUID開頭的行的第一個字段

relational expression:關係表達式,結果爲"真"纔會實處理
真:結果爲非0值,非空字符串
假:結果爲空字符串或0值

line ranges:行範圍 表示從哪行開始,到哪行結束
startline,endline:/pat1/,/pat2/不支持直接給出數字格式
示例:表示從以root開始的行,到以nobody開始的行

[root@CentOS7 data]#awk '/^root/,/^nobody/{print $1}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
.
.
.
nobody:x:99:99:Nobody:/:/sbin/nologin
[root@CentOS7 data]#

BEGIN/END模式
BEGIN{}:僅在開始處理文件中的文本之前執行一次
END{}:僅在文本處理完成之後執行一次

[root@CentOS7 data]#awk -F: 'BEGIN{print "USER USERID"}{print $1 ":" $3}END{print "END FILE"}' /etc/passwd
USER USERID
root:0
.
.
.
END FILE

awk循環

if-else語句
語法:if(條件){statement;...}[else statement]
if(){}else if(){}else{}
使用場景:對awk取得的整行或某個字段做條件判斷
示例:顯示ID大於等於1000的行的第一,第3字段

[root@CentOS7 data]#awk -F: '{if($3&gt;=1000)print $1,$3}' /etc/passwd
nfsnobody 65534
liuqiyou 1000
[root@CentOS7 data]#awk -F: '{if($NF=="/bin/bash")print $1}' /etc/passwd
root
liuqiyou
[root@CentOS7 data]#awk -F: '{if($3&gt;=1000) printf "Common user: %s\n",$1; else printf "root or Sysuser: %s\n",$1}'
/etc/passwd
root or Sysuser: root
.
.
.
root or Sysuser: tcpdump
Common user: liuqiyou
[root@CentOS7 data]#awk 'BEGIN{test=100;if(test&gt;90){print "very good "}else if(test&gt;60){print " goood"}else{print "no pass"}}'
very good

while 循環
語法:while(條件){動作}
條件"真",進入循環;條件"假",退出循環
使用場景:
對一行內的多個字段逐一處理時使用
對數組中的各元素 逐一處理時使用
示例:

[root@CentOS7 data]#awk '/^[[:space:]]*linux16/{i=1;while(i&lt;=NF){print $i,length($i);i++}}' /etc/grub2.cfg
linux16 7
/vmlinuz-3.10.0-957.el7.x86_64 30
root=UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
LANG=en_US.UTF-8 16
linux16 7
/vmlinuz-0-rescue-64dc0677454740549e82eabaf3619f3c 50
root=UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
[root@CentOS7 data]#awk 'BEGIN{i=1;sum=0;while(i&lt;=100){sum+=i;i++}print sum}'
5050

do-while循環
語法:do{}while()
先執行一次循環體後做條件判斷,最少執行一次

[root@CentOS7 data]#awk 'BEGIN{total=0;i=0;do{total+=i;i++;}while(i&lt;=100);print total}'
5050

for循環
語法:for(i=0;i<=100;i++){動作}
特殊用法:遍歷數組是的元素
for(i in array){print i,array[i]}

[root@CentOS7 data]#awk '/^[[:space:]]*linux16/{for(i=1;i&lt;=NF;i++){print $i,length($i)}}' /etc/grub2.cfg
linux16 7
/vmlinuz-3.10.0-957.el7.x86_64 30
root=UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
LANG=en_US.UTF-8 16
linux16 7
/vmlinuz-0-rescue-64dc0677454740549e82eabaf3619f3c 50
root=UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
[root@CentOS7 data]#awk 'BEGIN{for(i=1;i&lt;=100;i++)sum+=i;print sum}'
5050

switch語句
語法:switch(expression){case VALUE1 or /PEGEXP/:statement1;case VALUE2 or /REGEXP2/}

break和continue
break 跳出整個循環,提前結束循環

[root@CentOS7 data]#awk 'BEGIN{sum=0;for(i=1;i&lt;=100;i++){if(i==66)break;sum+=i}print sum}'
2145

continue 跳出本次循環,進入下一次循環

[root@CentOS7 data]#awk 'BEGIN{sum=0;for(i=1;i&lt;=100;i++){if(i%2==0)continue;sum+=i}print sum}'
2500

next:跳出本行循環,進入下一行循環

awk數組

關聯數組:array[index-expession]
index-expession:

1、可使用任意字符串;字符串要使用雙引號括起來
2、如果某數組元素事先不存在,在引用 時,awk會自動創建些元素,並將其值初始化爲"空串"
3、若要判斷數組中是否存在某元素,要使用"index in array"格式進行遍歷

[root@CentOS7 data]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}'
Monday
[root@CentOS7 data]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["tue"]}'
Tuesday

去除重複的行

[root@CentOS7 data]#awk '{!line[$0]++;print $0,line[$0]}' /etc/passwd

使用for循環遍歷數組中的每個元素
for(var in array){for-body}
var會遍歷arrayr的每個索引

[root@CentOS7 data]#netstat -tan |awk '/^tcp/{state[$NF]++}END{for(i in state){print i,state[i]}}'
LISTEN 9
ESTABLISHED 1
[root@CentOS7 data]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays){print i,weekd
asys[i]}}'
tue
mon

awk函數

數值處理:

rand():返回0到1之間一個隨機數
awk 'BEGIN{STAND();for(i=1;i&lt;=10;i++)print int(rand()*100)}'

字符串處理:
length([s]):返回指定字符串的長度

[root@CentOS7 data]#awk -F: '{print length($0)}' /etc/passwd

sub(r,s,[t]):對t字符串搜索r表示的模式匹配的內容,並全部替換爲s所表示的內容

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

gsub(r,s[t]):對t字符串進行搜索r表示的模式匹配的內容,並全部替換爲s所表示的內容

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

split(s,array,[r]):以r爲分隔符,切割字符串s,並將切割後的結果保存到array所表示的數組中,第一個索引值爲1,第二個索引值爲2,...

[root@CentOS7 data]#netstat -tn | awk '/^tcp\&gt;/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}'
172.22.37.100 1

自定義函數
自定義函數格式

function name ( parameter, parameter, ... ) {
  statements
  return expression
}

調用系統命令

awk中調用shell命令

system命令
空格是awk中的字符串連接符,如果system中需要使用awk中的變量,可以使用空格分隔,或者說除了awk的變量外其他一律用""引用起來

[root@CentOS7 data]#awk 'BEGIN{system("hostname")}'
CentOS7.localdomain
[root@CentOS7 data]#awk 'BEGIN{score=100;system("echo your scores is "score)}'
your scores is 100

awk腳本

將awk程序寫成腳本,直接調用或執行

[root@CentOS7 data]#vim f1.awk
#!/bin/awk
{if($3>=1000)print $1,$3}
[root@CentOS7 data]#awk -F: -f f1.awk /etc/passwd
nfsnobody 65534
liuqiyou 1000 
[root@CentOS7 data]#vim f2.awk
#!/bin/awk -f
#this is a awk script
{if($3>=1000)print $1,$3}
[root@CentOS7 data]#chmod +x f2.awk
[root@CentOS7 data]#./f2.awk -F: /etc/passwd
nfsnobody 65534
liuqiyou 1000

向awk腳本傳遞參數

格式:awkfile var=value var2=value2...inputfile
注意:在BEGIN過程中不可用。直到首行輸入完成以後,變量纔可用。可以能完-v參數,讓awk在執行BEGIN之前得到變量的值。命令行每一個指定的變量都要一個-v參數

[root@CentOS7 data]#vim test.awk
#!/bin/awk -f
{if($3>=min && $3<=max)print $1,$3}
[root@CentOS7 data]#chmod +x test.awk
[root@CentOS7 data]#./test.awk -F: min=100 max=200 /etc/passwd
systemd-network 192
abrt 173
rtkit 172
pulse 171
qemu 107
usbmuxd 113
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章