gawk


awk

文本處理grep,sed,awk

字符串處理: 切片,查找替換,查找刪除,變量賦值

grep 文本過濾器 分別有:egrep(等同grep -e),fgrep(最快,不支持正則表達式),grep

sed  流編輯器,(模式空間,保持空間)

awk 文本處理報告生成器 (Aho,Werinberger,Kernighan),以定義好的格式輸出,在linux上為gawk,之前還有nawk

      數組:declare -a

      關聯數組: declare -A

     

[root@localhost ~]# ls -l /usr/bin/awk 
lrwxrwxrwx. 1 root root 4 3月  28 20:26 /usr/bin/awk -> gawk

用法:

  gawk [ POSIX or GNU style options ] -f program-file [ -- ] file ...

  gawk [ POSIX or GNU style options ] [ -- ] program-text file ..

選項;

-F 分隔符,可以指定多個,默認空格

-v 自定義變量

[root@localhost ~]# awk -v a=b 'BEGIN{print a}'
b
[root@localhost ~]# awk  'BEGIN{a="b";print a}'
b

 

輸出:

一. -print

   print item1,item2,...

1,各項目之間用逗號隔開,而輸出以空白字符分隔,如果挨着寫,則輸出也是挨着,而且可以和print挨着;

[root@localhost ~]# cat awk.test 
This is a test
[root@localhost ~]# awk '{print $1,$2,$3,$4}' awk.test 
This is a test
[root@localhost ~]# awk '{print$1$2$3$4}' awk.test 
Thisisatest

 

2,指定分隔符號,在BEGIN模式指定,BEGIN后是花括號,圓括號算語法錯誤,分隔符號需要用雙引號引起來,單引號算語法錯誤,

awk: cmd. line:1: BEGIN(OFS="#"){print $1,$2,$3,$4}
awk: cmd. line:1:      ^ syntax error
[root@localhost ~]# awk  'BEGIN{OFS="#"}{print $1,$2,$3,$4}' awk.test
This#is#a#test
[root@localhost ~]# awk  'BEGIN{OFS='#'}{print $1,$2,$3,$4}' awk.test
awk: cmd. line:2: BEGIN{OFS=#}{print $1,$2,$3,$4}
awk: cmd. line:2:           ^ syntax error

3,可以在輸出顯示條目之間加入一些其他的輸出字符,被當做獨立的item,需要用雙引號引起來,例如:

[root@localhost ~]# awk  'BEGIN{OFS="#"}{print $1,$2,"TESTSTRING",$3,$4}' awk.test 
This#is#TESTSTRING#a#test

4,可以在輸出的條目之間加入換行符,為多行輸出:

[root@localhost ~]# awk 'BEGIN{print "line one\nline two\nline three"}'
line one
line two
line three

 

 

二,awk變量

awk內置變量之記錄變量 (FS,OFS,RS,ORS,NR,NF )

FS:Field Separator 讀取文件時使用的字段分隔符,默認是空白字符

     在BIEGIN'{}'中指定,或者在'{action}'外 -F 指定,如果要指定多個分隔符要用 [] 括起來,字符串還要用引號引起來,可以用正則表達式,當把FS指定為空時,awk會把一行中的每個字符當作一列來處理,awk會將連續的 空格 或 制表符(\t) 或 換行符(\n) 作為列的分隔符,如果只指定(默認)空格,則多個算空格算一個,如果指定多個分隔符,空白將計數。


[root@localhost ~]# echo '1,2,3' | awk -F , '{print $1}'
1
[root@localhost ~]# echo '1,2,3' | awk 'BEGIN{FS=","}{print $1}'
1
[root@localhost ~]# echo '1,2,3' | awk 'BEGIN{FS="[,]"}{print $1}'
1
[root@localhost ~]# echo '1,2,3' | awk 'BEGIN{FS="[',']"}{print $1}'
1

錯誤
[root@localhost ~]# echo '1,2,3' | awk 'BEGIN{FS=,}{print $1}'
awk: BEGIN{FS=,}{print $1}
awk:          ^ syntax error
[root@localhost ~]# echo '1,2,3' | awk 'BEGIN{FS=[,]}{print $1}'
awk: BEGIN{FS=[,]}{print $1}
awk:          ^ syntax error
[root@localhost ~]# echo '1,2,3' | awk 'BEGIN{FS='[,]'}{print $1}'
awk: BEGIN{FS=[,]}{print $1}
awk:          ^ syntax error
[root@localhost ~]# echo '1,2,3' | awk 'BEGIN{FS=[',']}{print $1}'
awk: BEGIN{FS=[,]}{print $1}
awk:          ^ syntax error [root@localhost
~]# echo '1,2,3' | awk 'BEGIN{FS=[","]}{print $1}' awk: BEGIN{FS=[","]}{print $1} awk: ^ syntax error

 

如果要同時指定多個分隔符,且空白開始計數

[root@localhost ~]# sed -n '13,14p' /etc/passwd
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
[root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -F : '{print $5}' gopher FTP User [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -F "[: ]" '{print $5}' gopher FTP [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -F "[ :]" '{print $5}' gopher FTP [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -F '[ :]' '{print $5}' gopher FTP [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -F'[ :]' '{print $5}' gopher FTP [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -F' :' '{print $5}' [root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -F " :" '{print $5}'

 空白計數比較:

[root@localhost ~]# echo '1,2,3 4  5' | awk 'BEGIN{FS="[ ,]"}{print $3}'
3
[root@localhost ~]# echo '1,2,3 4  5' | awk 'BEGIN{FS="[ ,]"}{print $4}'
4
[root@localhost ~]# echo '1,2,3 4  5' | awk 'BEGIN{FS="[ ,]"}{print $5}'

[root@localhost ~]# echo '1,2,3 4  5' | awk 'BEGIN{FS="[ ,]"}{print $6}'
5
[root@localhost ~]# echo '1,2,3 4  5   6' | awk -v OFS="|" 'BEGIN{FS="[    ,]"}{print $1,$2,$3,$4,$5,$6,$7,$8,$9}'
1|2|3|4||5|||6
[root@localhost ~]# echo '1 2 3 4  5   6' | awk -v OFS="|" 'BEGIN{FS=" "}{print $1,$2,$3,$4,$5,$6}'
1|2|3|4|5|6
[root@localhost ~]# echo '1 2 3 4  5   6' | awk -v OFS="|" '{print $1,$2,$3,$4,$5,$6}'
1|2|3|4|5|6

其他:

echo '1ab2bc3cd4de5' | awk 'BEGIN{FS="[a-z]+"}{print $1,$2,$5}'
1 2 5

 

 

OFS:Output Field Separator 輸出分隔符

[root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -v OFS=" " -F "[ :]" '{print $5,$NF}' 
gopher /sbin/nologin
FTP /sbin/nologin
[root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -v OFS="" -F "[ :]" '{print $5,$NF}' 
gopher/sbin/nologin
FTP/sbin/nologin
[root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -v OFS="++" -F "[ :]" '{print $5,$NF}' 
gopher++/sbin/nologin
FTP++/sbin/nologin

   如果輸出字段之間沒有分隔,即print的各字段沒有逗號,則在之前OSF定義的輸出分隔符不起作用

[root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -v OFS="++++" -F "[ :]" '{print $5$NF}' 
gopher/sbin/nologin
FTP/sbin/nologin
[root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -v OFS="++++" -F "[ :]" '{print $5,$NF}' 
gopher++++/sbin/nologin
FTP++++/sbin/nologin

RS:Record Separator 讀取文件時使用的行分隔符,默認換行符為\n,可以指定一個正則表達式為讀取換行符

     RT是利用RS匹配出來的內容,如果RS是固定某個值時,RT就是RS的內容

     當RS指定為空時,awk會先自動以多行空格為行分割符號,如果沒有空行,就以讀取到的所有內容中的空白為分割符

    

ORS:Output Row Separator 輸出換行符,print之間的字段是否有逗號分隔不影響輸出換行符的定義和作用

      可以把ORS理解成RS的反過程

[root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -v ORS="\n" -F "[ :]" '{print $5,$NF}' 
gopher /sbin/nologin
FTP /sbin/nologin
[root@localhost ~]# sed -n '13,14p' /etc/passwd|awk -v ORS="++" -F "[ :]" '{print $5,$NF}' 
gopher /sbin/nologin++FTP /sbin/nologin++[root@localhost ~]# 
[root@localhost ~]# 

 

awk內置變量之數據變量

NR:Number of input Records ,awk命令所處理的記錄數,如果有多個文件,這個數目會把所處理的多個文件統一進行計數

NF:Number of Field 當前記錄的field個數,總數,即容易理解$NF則表示最后一個字段

[root@localhost ~]# awk '{print NF}' awk.test 
4

 

FNR:與NR不同的是,FNR用於記錄正在處理的行是當前這一文件中被處理的行數(如有兩個100行的文件,處理到第二各文件的第20行,NR=120,FNR=20)

[root@localhost ~]# awk '{print NR}' /etc/fstab /etc/issue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@localhost ~]# awk '{print FNR}' /etc/fstab /etc/issue
1
2
3
4
5
6
7
8
9
10
11
1
2
3

 

ARGV:數組,保存命令行本身這個字符串,如awk '{print $0}' awk.test 這條命令中,AVGV[0] 保存awk,AVGV[1] 保存 awk.test

ARGC:awk命令行的參數個數

FILENAME:awk命令所處理的文件的名稱

ENVIRON:當前shell環境變量及其值的關聯數組:如

[root@localhost ~]# awk 'BEGIN{print ENVIRON["PATH"]}'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

 

用戶自定義變量(2種方式)

gawk允許用戶自定義變量以便在代碼中用到,變量名命名規則和大多數的編程語言相同,只能用字母,數字,和下划線,且不能以數字開頭,gawk變量名稱區分字符大小寫

a.在腳本中給變量賦值使用賦值語句進行:如

[root@localhost ~]# awk 'BEGIN{var="variable testing";print var}'
variable testing

b,也可以用-v 定義變量,且在awk中,變量不需要加$,在awk中$的意義是字段,在加BEGIN只執行一次,在{}的action中,語句和語句要使用分號隔開

[root@localhost ~]# awk -v var="varialbe testing" 'BEGIN{print var}'
varialbe testing

 

三,printf的使用

 printf 命令格式: printf format item1,item2...

1,與print命令最大的不同是,printf需要指定格式

2,format用於指定后面每一個item的輸出格式

3,printf不會自動打印換行符\n

format格式都以%開頭(只針對變量格式化

例如:觀察其中輸出冒號的位置!

[root@localhost ~]# awk -F: '{$3>=500?usertype="commom user":usertype="Administrator or System user";printf "%15-s %-s \n",$1":",usertype}' /etc/passwd|tail -5
apache:         Administrator or System user 
pulse:          Administrator or System user 
sshd:           Administrator or System user 
tcpdump:        Administrator or System user 
Gandefeng:      commom user 

   如果冒號加在格式中:

[root@localhost ~]# awk -F: '{$3>=500?usertype="commom user":usertype="Administrator or System user";printf "%15-s  :  %-s \n",$1,usertype}' /etc/passwd|tail -5
apache           :  Administrator or System user 
pulse            :  Administrator or System user 
sshd             :  Administrator or System user 
tcpdump          :  Administrator or System user 
Gandefeng        :  commom user 

 

%c 顯示字符的ASSII碼

%d ,%i 十進制整數(%+d 表示顯示數值符號)

%e ,%E 科學記數法顯示數值

%f 顯示浮點數

%g,%G 以科學計數法的格式或浮點數的格式顯示數值

%s 顯示字符串(%-s 左對齊,默認又對其)

%u 無符號的整數

%% 顯示百分號自身

修飾符

N 顯示寬度

-  左對齊(默認右對齊)

+ 顯示數值符號

 

四 awk的操作符

算數操作符

-x 負值

+x 轉換為數值

x^y 次方

x**y 次方

x/y 除

x+y 

x-y

x%y

賦值操作符

=

+=

-=

*=

/=

%=

^=

**=

++

 --

需要注意的是 如果某模式為=號 此時使用/*/ 肯能出現語法錯誤,應以/[=]/ 替代

 

布爾值

awk中,任何非0值或非空字符串都為真,反之就為假比較操作符

x < y    True if x is less than y

x <= y  True if x is less or equel to y

x  > y   True if x is greater than y

x > = y True if x is greater or equel to y

x == y  True if x is equel to y

x !=y    True if x is not equel to y

x ~ y    True if the string x matches the regexp denoted by y

x !~y   True if the string x does not match the regexp denoted by y

表達式間的邏輯關系符

&&

||

條件表達式

selector?if-true-exp:if-false-exp

函數調用

function_name (paral1,para2)

 

awk 常用模式

1 正則表達式  /regexp/ 

例如:顯示以G開頭的用戶名

[root@localhost ~]# awk -F : '/^G/ {print $1}' /etc/passwd
Gandefeng

2 表達式,其值為非0或非空字符串時滿足條件

例如:顯示使用bash的用戶

[root@localhost ~]# awk -F : '$7~"bash$" {print $1,$7}' /etc/passwd
root /bin/bash
Gandefeng /bin/bash

例如;顯示不為nologin的,格式輸出

[root@localhost ~]# awk -F : '$7!~"nologin$" {printf "%-30s%-20s\n",$1,$7}' /etc/passwd
root                          /bin/bash           
sync                          /bin/sync           
shutdown                      /sbin/shutdown      
halt                          /sbin/halt          
Gandefeng                     /bin/bash  

3 匹配范圍

例如:從第一個以uid為0開頭的行到第一個以sync結尾的行

[root@localhost ~]# awk -F : '$3==0,$7~"sync" {printf "%-30s%-20s\n",$1,$7}' /etc/passwd
root                          /bin/bash           
bin                           /sbin/nologin       
daemon                        /sbin/nologin       
adm                           /sbin/nologin       
lp                            /sbin/nologin       
sync                          /bin/sync      

4 BEGIN/END模式,僅在awk的開頭前運行一次和命令結束前最后一行處理完之后運行一次

例如:在上面實例基礎上加首行

[root@localhost ~]# awk -F : 'BEGIN{printf"%-10s%-10s%-20s\n","name","uid","shell"}$3==0,$7~"sync"{printf "%-10s%-10s%-20s\n",$1,$3,$7}END{print "end"}' /etc/passwd
name      uid       shell               
root      0         /bin/bash           
bin       1         /sbin/nologin       
daemon    2         /sbin/nologin       
adm       3         /sbin/nologin       
lp        4         /sbin/nologin       
sync      5         /bin/sync           
end

5 空模式 文件的每一行都要做處理

 

 

和尾行,同時匹配,注意需要BEGIN需要在匹配的前面

 

6 行限制范圍

[root@localhost ~]# awk -F : '(NR>=1&&NR<=3){print $1}' /etc/passwd
root
bin
daemon

 startline和endline默認匹配最大范圍

[root@localhost ~]# awk -F : '/^r/,/^s/{print $1}' /etc/passwd
root
bin
daemon
adm
lp
sync
rpc
vcsa
rtkit
abrt
avahi-autoipd
saslauth
rpcuser
nfsnobody
haldaemon
gdm
ntp
apache
pulse
sshd

 

 

 

常用的action

1 expression

2 control statements

3 compound statements

4 input statements

5 output statements

 

五 控制語句

1 if-else

if (condition) {then-body} else {[else-body]}

例如:判斷管理員

awk -F : '{if($1=="root")print $1,"admin";else print $1,"common user"}' /etc/passwd

       格式化輸出

 awk -F : '{if($1=="root")printf "%-15s:%s\n",$1,"admin";else printf "%-15s:%s\n",$1,"common user"}' /etc/passwd

      統計uid大於500的用戶

[root@localhost ~]# awk -F : -v sum=0 '{if($3>=500) sum++}END{print sum}' /etc/passwd
13

 

2 while

while (condition){statement1;statement2;...}

例:顯示每一行字符串長度大於等於4的字段

awk -F : '{i=1;while(i<=NF) {if (length($i)>=4) {print $i};i++}}' /etc/passwd

 

3 do-while

do {statement1,statement2,...} while (condition)

awk -F : '{i=1;do {print $1,i++}while(i<=3)}' /etc/passwd

 

4 for

for ( variable assignment; condition; iteration process) {statement1,statement2...}

例:循環3次顯示$1 遵循C語言風格

awk -F : '{for (i=1;i<=3;i++) print $1}' /etc/passwd

for 還可以遍歷數組元素

例:遍歷所有字段顯示大於4的字段

awk -F : '{for (i=1;i<=NF;i++) {if (length($i)>=4) {print $i}}}' /etc/passwd

 

5 case

swith (expression) { case value or /regexp/: statement1,statement2,... default: statement1,....}

 

6 break和contiune 用於循環或case語句中的終止或繼續

7 next 提前結束本行文本的處理,並接着處理下一行

 例:顯示ID為奇數的用戶

awk -F : '{if($3%2==0) next;print $1,$3}' /etc/passwd

 

七 數組

awk數組的下標從1開始,也可自己定義,可以使用任意字符串作為下標

例:統計各shell出現次數

[root@localhost ~]# awk -F : '{shell [$NF]++}END{for(A in shell){print A,shell[A]}}' /etc/passwd
/bin/sync 1
/bin/bash 2
/sbin/nologin 38
/sbin/halt 1
/sbin/shutdown 1

例:統計網絡狀態

root@localhost ~]# netstat -tan|awk '/^tcp/{state[$NF]++}END{for (A in state) print A,state[A]}'
LISTEN 9
ESTABLISHED 2

例:統計日志文件IP地址的訪問量

[root@localhost ~]# awk '{counts[$1]++};end {for (url in counts) print counts[url],url}' /var/log/httpd/access_log

 例:9x9乘法表

[root@localhost ~]# seq 9|sed 'H;g'|awk -v RS='' '{for(i=1;i<=NF;i++){printf"%dx%d=%d%s",i,NR,i*NR,i==NR?"\n":"\t"}}'

 


免責聲明!

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



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