文本三劍客之三---awk命令用法


awk命令

awk是一種編程語言,用於在linux/unix下對文本和數據進行處理。數據可以來自標准輸入(stdin)、一個或多個文件,或其它命令的輸出。它支持用戶自定義函數和動態正則表達式等先進功能,是linux/unix下的一個強大編程工具。它在命令行中使用,但更多是作為腳本來使用。awk有很多內建的功能,比如數組、函數等,這是它和C語言的相同之處,靈活性是awk最大的優勢。

awk命令格式和選項

語法形式

awk [options] 'script' var=value file(s) awk [options] -f scriptfile var=value file(s)

常用命令選項

-F fs   fs指定輸入分隔符,fs可以是字符串或正則表達式,如-F:
-v var=value   賦值一個用戶定義變量,將外部變量傳遞給awk
-f scripfile  從腳本文件中讀取awk命令
-m[fr] val   對val值設置內在限制,-mf選項限制分配給val的最大塊數目;-mr選項限制記錄的最大數目。這兩個功能是Bell實驗室版awk的擴展功能,在標准awk中不適用。

awk模式和操作

awk腳本是由模式和操作組成的。

模式

模式可以是以下任意一個:

/正則表達式/:使用通配符的擴展集。
關系表達式:使用運算符進行操作,可以是字符串或數字的比較測試。
模式匹配表達式:用運算符~(匹配)和~!(不匹配)。
BEGIN語句塊、pattern語句塊、END語句塊:

操作

操作由一個或多個命令、函數、表達式組成,之間由換行符或分號隔開,並位於大括號內,主要部分是:

awk腳本基本結構

awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file

一個awk腳本通常由:BEGIN語句塊、能夠使用模式匹配的通用語句塊、END語句塊3部分組成,這三個部分是可選的。任意一個部分都可以不出現在腳本中,腳本通常是被單引號雙引號中,例如:

awk 'BEGIN{ i=0 } { i++ } END{ print i }' filename
awk "BEGIN{ i=0 } { i++ } END{ print i }" filename

awk的工作原理

awk 'BEGIN{ commands } pattern{ commands } END{ commands }'
  • 第一步:執行BEGIN{ commands }語句塊中的語句;
  • 第二步:從文件或標准輸入(stdin)讀取一行,然后執行pattern{ commands }語句塊,它逐行掃描文件,從第一行到最后一行重復這個過程,直到文件全部被讀取完畢。
  • 第三步:當讀至輸入流末尾時,執行END{ commands }語句塊。

BEGIN語句塊在awk開始從輸入流中讀取行之前被執行,這是一個可選的語句塊,比如變量初始化、打印輸出表格的表頭等語句通常可以寫在BEGIN語句塊中。

END語句塊在awk從輸入流中讀取完所有的行之后即被執行,比如打印所有行的分析結果這類信息匯總都是在END語句塊中完成,它也是一個可選語句塊。

pattern語句塊中的通用命令是最重要的部分,它也是可選的。如果沒有提供pattern語句塊,則默認執行{ print },即打印每一個讀取到的行,awk讀取的每一行都會執行該語句塊。

示例:

[root@centos6~]#echo -e "A line 1\nA line 2" | awk 'BEGIN{ print "Start" } { print } END{ print "End" }'
Start
A line 1
A line 2
End

當使用不帶參數的print時,它就打印當前行,當print的參數是以逗號進行分隔時,打印時則以空格作為定界符。在awk的print語句塊中雙引號是被當作拼接符使用,例如:

示例:

[root@centos6~]#echo | awk '{ var1="v1"; var2="v2"; var3="v3"; print var1,var2,var3; }' 
v1 v2 v3

雙引號拼接使用:

[root@centos6~]#echo | awk '{ var1="v1"; var2="v2"; var3="v3"; print var1"="var2"="var3; }'
v1=v2=v3

{ }類似一個循環體,會對文件中的每一行進行迭代,通常變量初始化語句(如:i=0)以及打印文件頭部的語句放入BEGIN語句塊中,將打印的結果等語句放在END語句塊中。

awk內置變量(預定義變量)

說明:[A][N][P][G]表示第一個支持變量的工具,[A]=awk、[N]=nawk、[P]=POSIXawk、[G]=gawk

$n 當前記錄的第n個字段,比如n為1表示第一個字段,n為2表示第二個字段。 
$0 這個變量包含執行過程中當前行的文本內容。
[N] ARGC 命令行參數的數目。
[G] ARGIND 命令行中當前文件的位置(從0開始算)。
[N] ARGV 包含命令行參數的數組。
[G] CONVFMT 數字轉換格式(默認值為%.6g)。
[P] ENVIRON 環境變量關聯數組。
[N] ERRNO 最后一個系統錯誤的描述。
[G] FIELDWIDTHS 字段寬度列表(用空格鍵分隔)。
[A] FILENAME 當前輸入文件的名。
[P] FNR 同NR,但相對於當前文件。
[A] FS 字段分隔符(默認是任何空格)。
[G] IGNORECASE 如果為真,則進行忽略大小寫的匹配。
[A] NF 表示字段數,在執行過程中對應於當前的字段數。
[A] NR 表示記錄數,在執行過程中對應於當前的行號。
[A] OFMT 數字的輸出格式(默認值是%.6g)。
[A] OFS 輸出字段分隔符(默認值是一個空格)。
[A] ORS 輸出記錄分隔符(默認值是一個換行符)。
[A] RS 記錄分隔符(默認是一個換行符)。
[N] RSTART 由match函數所匹配的字符串的第一個位置。
[N] RLENGTH 由match函數所匹配的字符串的長度。
[N] SUBSEP 數組下標分隔符(默認值是34)。 

示例:

df | awk '{print $1,$3}'      $1和$3之間默認有空白符隔開

[root@centos7~]#df |awk '{print $1,$3}'
Filesystem Used
/dev/sda2 3909324
devtmpfs 0
tmpfs 0
tmpfs 10168
tmpfs 0
/dev/sda3 32992
/dev/sda1 166960
tmpfs 0

使用print $NF可以打印出一行中的最后一列字段,使用$(NF-1)則是打印倒數第二列字段,其他以此類推:

示例一:

[root@centos7~]#cat /etc/fstab

#
# /etc/fstab
# Created by anaconda on Thu Aug 22 15:21:16 2019
#
# 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=38dd5f68-4f30-411c-b80a-0f4a60b06c6f / xfs defaults 0 0
UUID=4357cc0e-6ee7-4a8f-8064-d1a54bdbf17f /boot xfs defaults 0 0
UUID=eb4bf5e6-2645-4b1c-bda8-12c5831b81c2 /data xfs defaults 0 0
UUID=b8c37e0b-3628-40b6-ac44-c36ca09b448f swap swap defaults 0 0

[root@centos7~]#awk '/^UUID/{print $(NF-2)}' /etc/fstab
defaults
defaults
defaults
defaults

示例二:

[root@centos7~]#cat f1.txt
aa dd cc
ss dd cc
aa cc nn

[root@centos7~]#awk '{print $NF}' f1.txt
cc
cc
nn

統計文件中的行數:

[root@centos7~]#df | awk '{print NR,$0}'     NR是顯示每行的行號,$0顯示所有行的內容

1 Filesystem     1K-blocks    Used Available Use% Mounted on

2 /dev/sda2      104806400 3909060 100897340   4% /

3 devtmpfs          740204       0    740204   0% /dev

4 tmpfs             756008       0    756008   0% /dev/shm

5 tmpfs             756008   10168    745840   2% /run

6 tmpfs             756008       0    756008   0% /sys/fs/cgroup

7 /dev/sda3       52403200   32992  52370208   1% /data

8 /dev/sda1        1038336  166960    871376  17% /boot

9 tmpfs             151204       0    151204   0% /run/user/0

示例三:

df |awk 'END{ print NR }' 

以上命令只使用了END語句塊,在讀入每一行的時,awk會將NR更新為對應的行號,當到達最后一行NR的值就是最后一行的行號,所以END語句塊中的NR就是文件的行數。

將外部變量值傳遞給awk

借助-v選項,可以將外部值(並非來自stdin)傳遞給awk:

[root@centos7~]#awk -v FS=":" '{print $1FS$3}'  /etc/passwd    給FS賦值:並以:作為分隔符顯示第1和3列信息。

root:0

bin:1

daemon:2

adm:3

lp:4

sync:5

shutdown:6

另一種傳遞外部變量方法:可以調用shell中的變量格式顯示

[root@centos7~]#fs=:;awk -v FS=$fs '{print $1FS$3}' /etc/passwd

root:0

bin:1

daemon:2

adm:3

lp:4

sync:5

shutdown:6

取出IP地址示例:

[root@centos7~]#df |awk -F"[[:space:]]+|%" '/\/dev\/sd/{print $1,$(NF-2)}'    以空白符合%作為分隔符,可以直接取出第1列和倒數第3列的設備信息和利用率

/dev/sda2 4

/dev/sda3 1

/dev/sda1 17

 

[root@centos7~]#df |awk -F"[[:space:]]+|%" '/\/dev\/sd/{print $1,$5}'      以空白符合%作為分隔符,可以直接取出第1列和倒第5列的設備信息和利用率

/dev/sda2 4

/dev/sda3 1

/dev/sda1 17

awk運算與判斷

作為一種程序設計語言所應具有的特點之一,awk支持多種運算,這些運算與C語言提供的基本相同。awk還提供了一系列內置的運算函數(如log、sqr、cos、sin等)和一些用於對字符串進行操作(運算)的函數(如length、substr等等)。這些函數的引用大大的提高了awk的運算功能。作為對條件轉移指令的一部分,關系判斷是每種程序設計語言都具備的功能,awk也不例外,awk中允許進行多種測試,作為樣式匹配,還提供了模式匹配表達式~(匹配)和~!(不匹配)。作為對測試的一種擴充,awk也支持用邏輯運算符。

算術運算符

算術操作符:
x+y, x-y, x*y, x/y, x^y, x%y
- x:轉換為負數
+x:將字符串轉換為數值
字符串操作符:沒有符號的操作符,字符串連接
賦值操作符:
=, +=, -=, *=, /=, %=, ^=,++, --
 下面兩語句有何不同
• awk ‘BEGIN{i=0;p rint ++i,i}’
• awk ‘BEGIN{i=0;print i++,i}’
 
特殊示例:
a+=5;等價於:a=a+5
 

操作符

比較操作符:

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

模式匹配符:

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

!~:是否不匹配

示例:

awk -F: '$0 ~ /root/{print $1}‘ /etc/passwd

[root@centos7~]#awk '$0~"^root"' /etc/passwd    $0顯示的行滿足^root的正則表達式進行打印

root:x:0:0:root:/root:/bin/bash

[root@centos7~]#awk '$0!~"^root"' /etc/passwd    $0顯示的行滿足非以^root為行首的正則表達式進行打印

[root@centos7~]#awk -F: '$3==0' /etc/passwd        第三列等於0的行進行打印

root:x:0:0:root:/root:/bin/bash

[root@centos7~]#lastb | awk '$3~/[[:digit:]]/{print $3}'    $3顯示的行滿足數字的正則表達進行打印第三列

192.168.34.100

192.168.34.1

192.168.34.1

192.168.34.1

192.168.34.1
[root@centos7~]#lastb  | awk '$3 ~  /^[[:digit:]]/{print $3}'  | sort | uniq -c |awk '$1  >=3{print  $1,$2}'    顯示IP地址連接次數大於3的進行打印

[root@centos7~]#awk -F: '($3>=1000){print $1,$3}' /etc/passwd            顯示第三列大於1000的第1行和第3行。

nfsnobody 65534

liu 1000

操作符

邏輯操作符:與&&,或||,非!

示例:

[root@centos7~]#awk -F: '$3>=1000 && $3<=2000{print $1,$3}' /etc/passwd  顯示第3列大於1000且小於2000的第1和第3列
liu 1000
[root@centos7~]#awk -F: '$3==0 || $3>=1000 {print $1,$3}' /etc/passwd   顯示等於0和大於等於1000的第一和第三列
root 0
nfsnobody 65534
liu 1000

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

selector?if-true-expression:if-false-expression

示例:

[root@centos7~]#awk -F:  '{$3>=1000?name="common user":name="system user";print name,$1,$3}' /etc/passwd    $3大於1000的顯示第一和第三列的name命名為common user,小於1000的,命名為system user
system user root 0
system user bin 1
system user daemon 2
system user adm 3 

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 "%-20s  %-10s\n",$1,$3}' /etc/passwd     提取第1列和第3列將其進行左對齊
root                  0            
bin                   1         
daemon           2         
adm                 3         
lp                     4         
sync                5   

awk PATTERN

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

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

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

awk '/^UUID/{print $1}' /etc/fstab

awk '!/^UUID/{print $1}' /etc/fstab

(3) relational expression: 關系表達式,結果為“真”才會被處理

真:結果為非0值,非空字符串

假:結果為空字符串或0值

(4)BEGIN/END模式

BEGIN{}:僅在開始處理文件中的文本之前執行一次

END{}:僅在文本處理完成之后執行一次

示例:

[root@centos7~]#df | awk -F"[[:space:]]+|%"  '/^\/dev\/sd/{print $1,$5}'    以空白和%為界限,取出當前的IP地址和設備:

/dev/sda2 4

/dev/sda3 1

/dev/sda1 17
ss  -nt | awk -F"[[:space:]]+|:"  '/ESTAB/{print  $6}'   取第6列的IP

ss  -nt | awk -F"[[:space:]]+|:"  '/ESTAB/{print  $(NF-2)}'  取倒數第三列的IP

 relational expression: 關系表達式,結果為“真”才會被處理

真:結果為非0值,非空字符串

假:結果為空字符串或0值

賦值為0的示例:得出的結果是假

[root@centos7~]# awk '0{print $0}' /etc/fstab   

[root@centos7~]#echo $?

0

賦值為空的示例:得出的結果是假

[root@centos7~]# awk '""{print $0}' /etc/fstab

[root@centos7~]#echo $?

0

為非0時就會顯示結果,就為真,示例如下:

[root@centos7~]# awk '"1"{print $0}' /etc/fstab

#

# /etc/fstab

# Created by anaconda on Thu Aug 22 15:21:16 2019

#

# 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=38dd5f68-4f30-411c-b80a-0f4a60b06c6f /                       xfs     defaults        0 0

UUID=4357cc0e-6ee7-4a8f-8064-d1a54bdbf17f /boot                   xfs     defaults        0 0

UUID=eb4bf5e6-2645-4b1c-bda8-12c5831b81c2 /data                   xfs     defaults        0 0

UUID=b8c37e0b-3628-40b6-ac44-c36ca09b448f swap                    swap    defaults        0 0

line ranges:行范圍

startline,endline:/pat1/,/pat2/ 不支持直接給出數字格式

示例:

[root@centos7~]#awk -F: '/^root/,/^adm/{print $1}' /etc/passwd  顯示第1列root開頭的行到adm開頭的行

root

bin

daemon

adm
[root@centos7~]#awk -F: '(NR>=10&&NR<=14){print NR,$1}' /etc/passwd  顯示第10行到14行的第1列

10 operator

11 games

12 ftp

13 nobody

14 systemd-netword

特殊示例:

打印奇數行:

[root@centos7~]#seq  10 | awk  'i=!i'     第一個i為空值,為假,取反就會打印出1,第二個出來為1時,為真,取反為假,就不打印2,以此類推,得出以下結果。

1

3

5

7

9

打印偶數行:

seq 10 | sed -n '1~2n'

seq 10 | sed -n '2~2n'

第一種情況:seq 10 | awk -v i="a" 'i=!i' 

第二種情況:[root@centos7~]#seq  10 | awk  '!(i=!i)'

      2

      4

      6

      8  

      10

 常用的action分類

• (1) Expressions:算術,比較表達式等

• (2) Control statements:if, while等

• (3) Compound statements:組合語句

• (4) input statements

• (5) 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

uexit

awk控制語句if-else

語法:if(condition){statement;…}[else statement]

if(condition1){statement1}else if(condition2){statement2}else{statement3}

使用場景:對awk取得的整行或某個字段做條件判斷

 

條件判斷語句:if

格式中語句1可以是多個語句,為了方便判斷和閱讀,最好將多個語句用{}括起來。awk分枝結構允許嵌套,其格式為:

示例:

awk 'BEGIN{
test=100;
if(test>90){
print "very good";
}
else if(test>60){
print "good";
}
else{
print "no pass";
}
}'

very good
[root@centos7~]#awk 'BEGIN{score=60;if(score<60){print "no pass"}else if(score<=80){print "so so"}else{print "good"}}'       兩種賦值變量方式都可以

[root@centos7~]#awk -v score=60 'BEGIN{if(score<60){print "no pass"}else if(score<=80){print "so so"}else{print "good"}}' 兩種賦值變量方式都可以

 so so

awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd

awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd

awk '{if(NF>5) print $0}' /etc/fstab

df -h|awk -F% '/^\/dev/{print $1}'|awk '$NF>=80{print $1,$5}‘

while循環

語法:while(condition){statement;…}

條件“真”,進入循環;條件“假”,退出循環

使用場景:

對一行內的多個字段逐一類似處理時使用

 對數組中的各元素逐一處理時使用

 

示例:

顯示第一行,且統計第一行有多少個字節,並打印每個字符。

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

root 4

x 1

0 1

0 1

root 4

/root 5

示例:

取出字符大於等於10的行,並統計字節數

[root@centos7~]#awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){if(length($i)>=10){print $i,length($i)};i++}}' /etc/grub2.cfg

/vmlinuz-3.10.0-957.el7.x86_64 30

root=UUID=38dd5f68-4f30-411c-b80a-0f4a60b06c6f 46

LANG=en_US.UTF-8 16

/vmlinuz-0-rescue-7a7fe51fce8c4639a5a046ac251485d0 50

root=UUID=38dd5f68-4f30-411c-b80a-0f4a60b06c6f 46

示例:生成隨機1000個數字

[root@centos7~]#for i in {1..1000};do if [ $i -eq 1 ];then echo -e "$RANDOM\c" >> f1.txt;else  echo -e ",$RANDOM\c" >> f1.txt;fi;done

然后在隨機數中取出最大值最小值:

[root@centos7~]#awk -F ',' '{i=2;max=$1;min=$1;while (i<=NF){if($i > max){max=$i}else if($i <min){min=$i};i++}}END{print "max="max,"min="min}' f1.txt

max=1653826510 min=8

do-while循環

語法:do {statement;…}while(condition)

意義:無論真假,至少執行一次循環體

示例:1+2..100求和

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

5050

for循環

語法:for(expr1;expr2;expr3) {statement;…}

常見用法:

for(variable assignment;condition;iteration process)

{for-body}

u特殊用法:能夠遍歷數組中的元素

語法:for(var in 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-957.el7.x86_64 30
root=UUID=38dd5f68-4f30-411c-b80a-0f4a60b06c6f 46
ro 2
rhgb 4
quiet 5
LANG=en_US.UTF-8 16
linux16 7
/vmlinuz-0-rescue-7a7fe51fce8c4639a5a046ac251485d0 50
root=UUID=38dd5f68-4f30-411c-b80a-0f4a60b06c6f 46
ro 2
rhgb 4
quiet 5

switch語句

語法:switch(expression) {case VALUE1 or /REGEXP/: statement1; case

VALUE2 or /REGEXP2/: statement2; ...; default: statementn}

break和continue

next:

continue語句:當 continue 語句用於 while 或 for 語句時,使程序循環移動到下一個迭代。

break語句:當 break 語句用於 while 或 for 語句時,導致退出程序循環。

示例:

awk 'BEGIN{total=0;for(i=1;i<=100;i++){if(i==50)break;total+=i};print total}'

next語句:能能夠導致讀入下一個輸入行,並返回到腳本的頂部。這可以避免對當前輸入行執行其他的操作過程。

示例:

awk -F: '{if(NR%2==0)next;print NR,$0}'  /etc/passwd  顯示的是奇數行

awk -F: '{if(NR%2==0)print NR,$0}'  /etc/passwd    顯示偶數行

數組應用

awk數組

關聯數組:array[index-expression]

uindex-expression:

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

• (2) 如果某數組元素事先不存在,在引用時,awk會自動創建此元素,並將其值

初始化為“空串”  很重要,比較被遺忘的一個點

• (3) 若要判斷數組中是否存在某元素,要使用“index in array”格式進行遍歷

 

數字做數組索引(下標):

Array[1]="sun"

Array[2]="kai"

字符串做數組索引(下標):

Array["first"]="www"

Array["last"]="name"

Array["birth"]="1987"

使用中print Array[1]會打印出sun;使用print Array[2]會打印出kai;使用print Array["birth"]會得到1987。

示例:

[root@centos7~]#awk 'BEGIN{title["coo"]="wang";title["ceo"]="ma";print title["coo"]}'

wang

示例: 類似於去重的功能

解釋:line[$0]第一次顯示的值為空值,然后取反就為真,打印第一個值,++會將第一次出現的值進行累加,然后取反為假,就不打印重復出現的值。

[root@centos7~]#awk '{!line[$0]++;print $0,line[$0]}' f1.txt  顯示當前的詳細過程,驗證第一次數組賦值為空值,取反為1.

aaa 1

sss 1

aaa 2

ccc 1

ccc 2

[root@centos7~]#awk '!line[$0]++' f1.txt

aaa

sss

ccc

[root@centos7~]#cat f1.txt

aaa

sss

aaa

ccc

ccc

數組for循環語句用法:

若要遍歷數組中的每個元素,要使用for循環

for(var in array) {for-body}

注意:var會遍歷array的每個索引

 

示例:

[root@centos7~]#awk 'BEGIN{titel["coo"]="ma";titel["ceo"]="lige";titel[3]="liu";for(i in titel){print i,titel[i]}}'

coo ma

ceo lige

3 liu

示例: 統計ip的tcp類型的次數

[root@centos7~]#netstat -tan | awk '/^tcp /{state[$NF]++}END{for(i in state){print i,state[i]}}'

LISTEN 7

ESTABLISHED 1

示例:  提取連接態的IP和個數

[root@centos7~]#ss -nt | awk -F"[[:space:]]+|:" '/ESTAB/{ip[$(NF-2)]++}END{for(i in ip){print i,ip[i]}}'

192.168.34.1 1

示例:  提取文件系統類型和計數

[root@centos7~]#awk '/^UUID/{type[$3]++}END{for(i in type){print i type[i]}}' /etc/fstab

swap1

xfs3

示例:分數求平均值

[root@centos6~]#cat f1.txt
name  sex      score
a    f         90
b    m    80
c    f      50
d    m    60

[root@centos6~]#awk '!/^name/{sum[$2]+=$3;num[$2]++}END{for(i in num){print i,sum[i]/num[i]}}' f1.txt
m 70
f 70

數值處理:

rand():返回0和1之間一個隨機數

示例:隨機生成四個數值,其中int是取整數,rand()默認取出的數值小數點兩位,*100增大十倍

[root@centos6~]#awk 'BEGIN{srand();for(i=1;i<=4;i++)print int(rand()*100)}'

5

12

52

84

取出一位100以內的隨機數:

[root@centos7~]#awk 'BEGIN{srand();print int(rand()*100)}'

56

字符串處理:

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

• sub(r,s,[t]):對t字符串搜索r表示模式匹配的內容,並將第一個匹配內容替換為s

示例:將第一列的:替換為-

[root@centos7~]#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~]#echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-",$0)'

2008-08-08 08-08-08

示例:將第一列全部替換為-

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

2008-08-08 08:08:08

• split(s,array,[r]):以r為分隔符,切割字符串s,並將切割后的結果保存至array所

表示的數組中,第一個索引值為1,第二個索引值為2,…

示例一:將整行以:形式進行分割,最后顯示當前行字符和序列號,其中i顯示序號,str[i]顯示處理后的字符

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

4 08

5 08

1 2008

2 08

3 08 08

示例二:整行以:為分割線,將第五列的ip地址取出並統計當前的次數

[root@centos7~]#ss -nt | awk '/^ESTAB/{split($5,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}'

192.168.34.1 1

自定義函數格式:

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

statements

return expression

}

示例:

cat fun.awk

function max(x,y) {

x>y?var=x:var=y   如果x>y則var=x,否則var=y

return var

}

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

awk -f fun.awk 

system命令用法:

空格是awk中的字符串連接符,如果system中需要使用awk中的變量可以使用

 

空格分隔,或者說除了awk的變量外其他一律用""引用起來

示例一:systeml  可以調用awk里邊的命令變量

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

centos7.localdomain 

示例二:

[root@centos7~]#awk 'BEGIN{system("ls /boot")}'

config-3.10.0-957.el7.x86_64 initramfs-3.10.0-957.el7.x86_64.img

efi symvers-3.10.0-957.el7.x86_64.gz

grub System.map-3.10.0-957.el7.x86_64

grub2 vmlinuz-0-rescue-7a7fe51fce8c4639a5a046ac251485d0

initramfs-0-rescue-7a7fe51fce8c4639a5a046ac251485d0.img  vmlinuz-3.10.0-957.el7.x86_64

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

示例一:調用文件

cat f1.awk

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

awk -F: -f f1.awk /etc/passwd

cat f2.awk

示例二:調用腳本文件

#!/bin/awk -f

#this is a awk script

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

加執行權限:chmod +x f2.awk

當前目錄執行調用腳本:

./f2.awk -F: /etc/passwd

向awk腳本傳遞參數

格式:

awkfile var=value var2=value2... Inputfile

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

示例:

cat test.awk

#!/bin/awk –f

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

chmod +x test.awk

./test.awk -F: min=100 max=200 /etc/passwd

練習:將以下文件內容中FQDN取出域名並根據其進行計數從高到低排序

http://mail.magedu.com/index.html

http://www.magedu.com/test.html

http://study.magedu.com/index.html

http://blog.magedu.com/index.html

http://www.magedu.com/images/logo.jpg

http://blog.magedu.com/20080102.html

 

答案:

[root@centos7~]#cat f1.txt

http://mail.magedu.com/index.html

http://www.magedu.com/test.html

http://study.magedu.com/index.html

http://blog.magedu.com/index.html

http://www.magedu.com/images/logo.jpg

http://blog.magedu.com/20080102.html

[root@centos7~]# awk -F"/" '{fqdn[$3]++}END{for(i in fqdn){print i,fqdn[i]}}' f1.txt | sort  -nr -k2

www.magedu.com 2

blog.magedu.com 2

study.magedu.com 1

mail.magedu.com 1

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM