行列轉換文本處理--awk xargs 回顧

 

 

awk 數組回顧:

9.1 數組

舉例:統計當前主機上每個TCP鏈接狀態以及每種鏈接狀態的數目【很是實用】
# netstat -tan | awk '/^tcp/{STATE[$NF]++}END{for (S in STATE) {print S,STATE[S]}}'  注:單引號內的都是PARTTEN,此句沒有ACTION【定義數組、變量儘可能大寫,小寫也不錯】
LISTEN 11
ESTABLISHED 1
解釋: 最後一列元素$NF做爲數組的下標,數組的元素是數字


array[index-expression]

index-expression可使用任意字符串;須要注意的是,若是某數據組元素事先不存在,那麼在引用其時,awk會自動建立此元素並初始化爲空串;所以,要判斷某數據組中是否存在某元素,須要使用index in array的方式。

要遍歷數組中的每個元素,須要使用以下的特殊結構:
for (var in array) { statement1, ... }
其中,var用於引用數組下標,而不是元素值;

例子:
netstat -ant | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
每出現一被/^tcp/模式匹配到的行,數組S[$NF]就加1,NF爲當前匹配到的行的最後一個字段,此處用其值作爲數組S的元素索引;

awk '{counts[$1]++}; END {for(url in counts) print counts[url], url}' /var/log/httpd/access_log
用法與上一個例子相同,用於統計某日誌文件中IP地的訪問量





[root@master interview]# cat b.txt 
001 wodi 12k

002 yingsui 15k

003 jeacen 10k

004 yideng 10k

005 kuqi 8k

006 xiaofen 6k

007 wodi 11k

008 yingsui 12k

009 jeacen 4k

010 kuqi 12k

011 yideng 11k

012 xiaofen 10k


awk 何時用變量,何時用數組:
如上題目:計算每一個人的總工資和平均工資,若有相同的行,變量沒法把多行相同元素分類累加,故用數組完成
答案:[root@xuegod68 mnt]# awk '{array[$2]+=$3;count[$2]++}END{for(key in array) print key,array[key]"k",array[key]/count[key]}' 3.txt
 
kuqi 20k 10
 
jeacen 14k 7
 
yingsui 27k 13.5
 
xiaofen 16k 8
 
wodi 23k 11.5
 
yideng 21k 10.5

以下題目:求出最後一列的均值,由於每行都相同,
[root@master interview]# cat a.txt 
asd ioq pas sqw zxs 11
asd ioq pas sqw zxz 22
asd ioq pas sqw zxw 33
asd ioq pas sqw zxd 44
asd ioq pas sqw zxe 55
答案:
[root@master interview]# awk '{sum+=$6}END{print sum/NR}' a.txt 
33



命令解析:
[root@master interview]# grep -v "^$" b.txt |awk '{a[$2]+=$3;count[$2]++}END{print a["wodi"]}'
a[$2] :表明數組元素a[wodi]的值,初值爲空,第一行執行後: a[wodi] = 空  +  12
count[$2]++  : 第一行執行後,count[wodi]初始爲空,count[wodi]這個元素的值自加1



[root@master interview]# netstat -ant|awk '{A[$NF]++}END{for (key in A)print key,A[key]}'
TIME_WAIT 2
CLOSE_WAIT 2
established) 1
SYN_SENT 2
State 1
ESTABLISHED 13
LISTEN 45








例題:統計下面兩個文件中,每行出現的頻率:
[root@master interview]# cat c.txt 
aaa
bbb
ccc
aaa
ddd
aaa
bbb
[root@master interview]# cat d.txt 
aaa
bbb
ccc
aaa
ddd
aaa
bbb

awk '{A[$1]++}END{for (key in A) print key,A[key]}' c.txt d.txt 





例題:統計文件中的URL
[root@master test]# cat a.txt 
http://www.baidu.com/index.html
http://www.163.com/1.html
http://www.cnblogs.com/index.html
http://www.cnblogs.com/index.html
http://www.cnblogs.com/index.html
http://www.cnblogs.com/index.html
http://www.baidu.com/2.html
http://www.163.com/index.html
http://www.qq.com/index.html
http://www.baidu.com/3.html
http://www.163.com/2.html
http://www.163.com/2.html
http://www.baidu.com/2.html
http://www.baidu.com/2.html
http://www.baidu.com/2.html

[root@master test]# cat a.txt| sort  |uniq -c|sort -rn            # 第一個sort把相同的行放一塊兒,uniq合併相同的行並輸出重複的次數
      4 http://www.cnblogs.com/index.html
      4 http://www.baidu.com/2.html
      2 http://www.163.com/2.html
      1 http://www.qq.com/index.html
      1 http://www.baidu.com/index.html
      1 http://www.baidu.com/3.html
      1 http://www.163.com/index.html
      1 http://www.163.com/1.html


awk方法1:$0表明整行; array[1]爲split函數分割結果的第一個部分,array[2]是域名,array[3]是uri 。
[root@master test]# awk '{split($0,array,"/+");var=array[2];count[var]++}END{for (k in count)print k,count[k]}' a.txt 
www.qq.com 1
www.cnblogs.com 4
www.baidu.com 6
www.163.com 4

awk方法2:
[root@master test]# awk -F "[/]+" '{A[$2]++}END{for (k in A) print k,A[k]}' a.txt 
www.qq.com 1
www.cnblogs.com 4
www.baidu.com 6
www.163.com 4

 

 awk補充:html

# awk的record和field相關變量,設置指定分割符、調整分隔符:

RS:Record Separator,RS是awk讀取文件時的行分隔符
ORS:Output Record Separate, ORS是awk輸出時的行結束符 更簡單的講,就是awk在輸出時,會在每行記錄後面增長一個ORS變量所設定的值。ORS的值只能設定爲字符串,默認狀況下,ORS的值是\n 
FS:Field Separator,字段分隔符
OFS:Out of Field Separator,輸出字段分隔符




單行單列相互轉換:
方法1:awk '{print $2}' a.txt | tr '\n' ' '
方法2:cat a.txt|xargs


多行、多列轉換:
name age
alice 21
ryan 30
轉換爲:
name alice ryan
age 21 30

awk '{ for(i=1;i<=NF;i++){ if(NR==1){ arr[i]=$i; }else{ arr[i]=arr[i]" "$i; } } } END{ for(i=1;i<=NF;i++){ print arr[i]; } }'  file.txt
# 使用一維數組,記錄每一列的組合串便可,當是第一行時賦值,不然都是累加,即字符串拼接。





[root@localhost ~]# cat a.txt 
123
43as
asd
ss
dd1
[root@localhost ~]# cat a.txt |awk 'BEGIN{RS="\n";ORS=" "}{print $1}END{printf "\n"}'               # {printf "\n"} 結尾加個換行符
123 43as asd ss dd1 
[root@localhost ~]# cat a.txt |awk 'BEGIN{ORS=" "}{print $1}END{printf "\n"}' | awk 'BEGIN{RS=" "}{print $1}'
123
43as
asd
ss
dd1




示例1:

1.txt

a|b|c

# 單行以|分割,變爲單列
awk 'BEGIN{ RS="|"; } { print $0 }'

a
b
c





FS、OFS例子:
[root@localhost ~]# cat c.txt 
123  123 rrr
43as qqq ttt
asd  aaa fff
ss   sss ggg
dd1  ddd hhh
[root@localhost ~]# cat c.txt |awk 'BEGIN{FS=" ";OFS="|"}{$1=$1;print $0}'  # $1=$1,awk只有對域有了操做,如$1=$1,OFS纔會生效
123|123|rrr
43as|qqq|ttt
asd|aaa|fff
ss|sss|ggg
dd1|ddd|hhh

[root@localhost ~]# cat c.txt |awk 'BEGIN{FS=" ";OFS="|"}{print $1,$2,$3}'
123|123|rrr
43as|qqq|ttt
asd|aaa|fff
ss|sss|ggg
dd1|ddd|hhh



修改分隔符:
例中「i----love----you」,「----」爲分隔符(FS),若是咱們想改成用其餘符號顯示能夠這樣:

awk 'BEGIN{ FS="----";OFS="*****" }{ print $1,$2,$3 }' filename

i*****love*****you



在理解了 RS 和 FS 以後,咱們來回顧開始的那句話:「awk是基於行列操做文本的」,這個說法實際上不是很準確,由於在改變了 RS 後,awk 中的「行」已經不是通常的「行」了
 一樣,改變了 FS 後,awk 中的「列」也已經不是通常的「列」了;  所以,準確的應該這樣講:「awk是基於 記錄(record) 和 域(field) 操做文本的」;當對域分隔符修改後,輸出時,要對域操做才能生效



綜合例題:
[root@localhost ~]# cat b.txt 
#
1
2
3
#
4
5
#
6
7
8
9
#

輸出爲:
123
45
6789

[root@localhost ~]# awk 'BEGIN{RS="\n";ORS=""}{print $1}' b.txt |awk 'BEGIN{RS="#"}{print $0}' |awk '{if($0!="")print}'
123
45
6789

# 過程:
這一列先轉化爲行:awk 'BEGIN{RS="\n";ORS=""}{print $1}' b.txt 
如:#123#45#6789#

再按#,按列切割;
[root@localhost ~]# awk 'BEGIN{RS="\n";ORS=""}{print $1}' b.txt |awk 'BEGIN{FS="#";OFS="\n"}{$1=$1;print $0}'

123
45
6789

最後去掉空行便可;











awk練習題
   wang     4
   cui      3
   zhao     4
   liu      3
   liu      3
   chang    5
   li       2
   
   
1 經過第一個域找出字符長度爲4的
2 當第二列值大於3時,建立空白文件,文件名爲當前行第一個域$1 (touch $1)
3 將文檔中 liu 字符串替換爲 hong
4 求第二列的和
5 求第二列的平均值
6 求第二列中的最大值
7 將第一列過濾重複後,列出每一項,每一項的出現次數,每一項的大小總和
   
   
   
1、字符串長度
 awk 'length($1)=="4"{print $1}'
2、執行系統命令
 awk '{if($2>3){system ("touch "$1)}}'
3、gsub(/r/,"s",域) 在指定域(默認$0)中用s替代r  (sed 's///g')
 awk '{gsub(/liu/,"hong",$1);print $0}' a.txt
4、列求和
 df -h | awk '{a+=$2}END{print a}'
5、列求平均值
 df -h | awk '{a+=$2}END{print a/NR}'
 df -h | awk '{a+=$2;b++}END{print a,a/b}' 
6、列求最大值
 df -h | awk 'BEGIN{a=0}{if($2>a) a=$2 }END{print a}'
7、將第一列過濾重複列出每一項,每一項的出現次數,每一項的大小總和

首先定義一個數組記錄重複項:A[$1]++

再定義一個數組作重複項對應值的累加和;B[$1]+=$2
[root@localhost ~]# cat a.txt |awk '{A[$1]++;B[$1]+=$2}END{for (i in A)print i,A[i],B[i]}'
cui 1 3
chang 1 5
li 1 2
wang 1 4
zhao 1 4
liu 2 6

 

 

 

 xargs:mysql

#xargs經常使用選項:

-n: 指定一次處理的參數個數

-d: 自定義參數界定符

-p: 詢問是否運行 later command 參數

-t : 表示先打印命令,而後再執行

-i : 逐項處理


# 多行變成單行

-bash-3.2# cat test.txt

a b c d e f

g o p q

-bash-3.2# cat test.txt |xargs

a b c d e f g o p q

 

#單行變成多行

-bash-3.2# cat test.txt

a b c d e f g o p q

-bash-3.2# cat test.txt |xargs -n 2

a b

c d

e f

g o

p q


#刪除某個重複的字符來作定界符

-bash-3.2# cat test.txt

Aaaagttttgyyyygcccc

-bash-3.2# cat test.txt |xargs -d g

aaaa tttt yyyy cccc



# 將全部文件重命名,逐項處理每一個參數


ls *.txt |xargs -t -i mv {} {}.bak

 

 

 

 

 

 

 

 

 

grep: 文本過濾器
    grep 'pattern' input_file ...

sed:流編輯器

awk: 報告生成器
    格式化之後,顯示

AWK a.k.a. Aho, Kernighan and Weinberger

new awk: nawk

gawk, awk



# awk [options] 'script' file1 file2, ... 【從多個文件中讀取文本信息,然後根據'script'(由'PATTERN { action }'組成)將其格式化爲特定的格式,再顯示之】
# awk [options] 'PATTERN { action }' file1 file2, ... 【只處理被PATTERN匹配到的行,action爲處理動做,常見的處理動做:print簡單打印,printf能夠自定義顯示格式】
    print, printf

awk經常使用指定分隔符的選項:-F    【默認空格分隔符】

[root@whiteskpc myscript]# cat awk.txt 
this is a test
[root@whiteskpc myscript]# awk '{print $0}' awk.txt 
this is a test
[root@whiteskpc myscript]# awk '{print $1}' awk.txt 
this
[root@whiteskpc myscript]# awk '{print $4}' awk.txt 
test
[root@whiteskpc myscript]# awk '{print $1,$4}' awk.txt 
this test

[root@whiteskpc myscript]# awk 'BEGIN{OFS="#"} {print $1,$4}' awk.txt     【指定輸出分隔符爲#,注意大寫】
this#test
[root@whiteskpc myscript]# awk 'BEGIN{OFS=":"} {print $1,$2,$3,$4}' awk.txt     【打印整個條目,用:分隔】
this:is:a:test





awk的輸出:

1、print
print的使用格式:
    print item1, item2, ...
例:
[root@whiteskpc myscript]# awk 'BEGIN{OFS=":"} {print $1,"hello",$2,$3,$4}' awk.txt     【添加一個字段,把一個文本字符串單作item輸出,注意雙引號而非單引號】
this:hello:is:a:test


要點:
1、各項目之間使用逗號隔開,而輸出時則以空白字符分隔;
2、輸出的item能夠爲字符串或數值、當前記錄的字段(如$1)、變量或awk的表達式;數值會先轉換爲字符串,然後再輸出;
3、print命令後面的item能夠省略,此時其功能至關於print $0, 所以,若是想輸出空白行,則須要使用print "";

例子:
# awk 'BEGIN { print "line one\nline two\nline three" }'
awk -F: '{ print $1, $3 }' /etc/passwd


2、awk變量

2.1 awk內置變量之記錄變量:
FS: field separator,讀取文件本時,所使用字段分隔符;
RS: Record separator,輸入文本信息所使用的換行符;
OFS: Output Filed Separator: 
ORS:Output Row Separator:

awk -F: 【指定輸入分隔符,讀取文本的時候以什麼爲分隔符】
OFS="#"    【輸出分隔符,打印文本時以什麼爲分隔符】
FS=":"  【FS也可指定輸入分隔符】


2.2 awk內置變量之數據變量:
NR: The number of input records,awk命令所處理的行的記錄數;若是有多個文件,這個數目會把處理的多個文件中的行統一計數;
NF:Number of Field,當前記錄的field個數;   【統計當前正在處理的行的字段總數】

例:
[root@whiteskpc myscript]# cat awk.txt 
this is a test
[root@whiteskpc myscript]# awk '{print NF}' awk.txt 
4
[root@whiteskpc myscript]# awk '{print $NF}' awk.txt 【表示打印當前行的最後一個字段】
test

[root@whiteskpc myscript]# awk '{print NR}' awk.txt 
1


FNR:facing number of input records 與NR不一樣的是,FNR用於記錄正處理的行是當前這一文件中被總共處理的行數;
ARGV: 數組,保存命令行自己這個字符串,如awk '{print $0}' a.txt b.txt這個命令中,ARGV[0]保存awk,ARGV[1]保存a.txt;
ARGC: awk命令的參數的個數;
FILENAME: awk命令所處理的文件的名稱;
ENVIRON:當前shell環境變量及其值的關聯數組;

如:awk 'BEGIN{print ENVIRON["PATH"]}'




說明:
awk處理兩個文件,第一個文件處理了100行,第二個文件處理了20行:則NR=121,FNR=21
即:NR是指對讀取處理的全部文件,處理了多少行。                【絕對計數】
    FNR是指對於當前正在處理的文件(不考慮其餘文件),在多少行。        【各自計數】
例:
[root@whiteskpc myscript]# cat awk.txt 
this is a test
this is a test
[root@whiteskpc myscript]# cat awk.txt >> awk1.txt 
[root@whiteskpc myscript]# cat awk1.txt 
this is a test
this is a test
this is a test
this is a test
[root@whiteskpc myscript]# awk '{print NR}' awk.txt 
1
2
[root@whiteskpc myscript]# awk '{print NR}' awk.txt awk1.txt 
1
2
3
4
5
6
[root@whiteskpc myscript]# awk '{print FNR}' awk.txt awk1.txt 
1
2
1
2
3
4


2.3 用戶自定義變量

gawk容許用戶自定義本身的變量以便在程序代碼中使用,變量名命名規則與大多數編程語言相同,只能使用字母、數字和下劃線,且不能以數字開頭。gawk變量名稱區分字符大小寫。


變量賦值兩種方式:
        【腳本中賦值變量,BEGIN模式;命令航中賦值變量awk -v】
2.3.1 在腳本中賦值變量

在gawk中給變量賦值使用賦值語句進行,例如:
awk 'BEGIN{var="variable testing";print var}' 【action中若是有多個語句,語句之間用分號隔開】

2.3.2 在命令行中使用賦值變量

gawk命令也能夠在「腳本」外爲變量賦值,並在腳本中進行引用。例如,上述的例子還能夠改寫爲:
awk -v var="variable testing" 'BEGIN{print var}'awk -v,variable ,表示-v後面跟了個變量名,然後給變量賦值,awk後面不帶文件一般使用BEGIN模式】

注意:在awk中打印變量值是不須要加$符號的,這點和bash不一樣!其實,加了$符號表示打印字段。









3、printf
printf命令的使用格式:
printf format, item1, item2, ...

要點:
1、其與print命令的最大不一樣是,printf須要指定format;
2、format用於指定後面的每一個item的輸出格式;
3、printf語句不會自動打印換行符;\n    【和print的區別】

format格式的指示符都以%開頭,後跟一個字符;以下: 【格式指示符與格式指示符之間不須要使用逗號或其餘符號分隔】
%c: 顯示字符的ASCII碼;
%d, %i:十進制整數;
%e, %E:科學計數法顯示數值;
%f: 顯示浮點數;
%g, %G: 以科學計數法的格式或浮點數的格式顯示數值;
%s: 顯示字符串;
%u: 無符號整數;
%%: 顯示%自身;

修飾符:  【修飾符加在%和字母之間】
N: 顯示寬度;
-: 左對齊;   【不加-表示右對齊】
+:顯示數值符號;

printf用法例子:
[root@whiteskpc myscript]# cat awk.txt 
this is a test
[root@whiteskpc myscript]# awk '{printf "%s\n",$1}' awk.txt 
this
[root@whiteskpc myscript]# awk '{printf "%10s\n",$1}' awk.txt     【N=10,寬度10個字符,沒有字符的用空白字符補齊】
      this
[root@whiteskpc myscript]# awk '{printf "%-10s\n",$1}' awk.txt  【左對齊,this右邊有十個空白字符】
this  
[root@whiteskpc myscript]# awk '{printf "%-10s,%-10s\n",$1,$3}' awk.txt 【顯示兩個字段方法】
this      ,a         
[root@whiteskpc myscript]# awk '{printf "%-10s%-10s\n",$1,$3}' awk.txt 【格式指示符與格式指示符之間不須要使用逗號或其餘符號分隔】
this      a 
[root@whiteskpc myscript]# awk '{printf "%-10s %-10s\n",$1,$3}' awk.txt 
this       a 

以科學計數法顯示每一個用戶的ID號碼:
# awk -F: '{printf "%-5d\n",$3}' /etc/passwd 【左對齊】         

# awk -F: '{printf "%-15s %i\n",$1,$3}' /etc/passwd



4、輸出重定向

print items > output-file
print items >> output-file
print items | command

特殊文件描述符:
/dev/stdin:標準輸入
/dev/sdtout: 標準輸出
/dev/stderr: 錯誤輸出
/dev/fd/N: 某特定文件描述符,如/dev/stdin就至關於/dev/fd/0;

例子:
# awk -F: '{printf "%-15s %i\n",$1,$3 > "/dev/stderr" }' /etc/passwd


6、awk的操做符:

6.1 算術操做符:

-x: 負值
+x: 轉換爲數值;
x^y: 
x**y: 次方
x*y: 乘法
x/y:除法
x+y:
x-y:
x%y:

6.2 字符串操做符:
只有一個,並且不用寫出來,用於實現字符串鏈接;

6.3 賦值操做符:
=
+=
-=
*=
/=
%=
^=
**=

++
--

須要注意的是,若是某模式爲=號,此時使用/=/可能會有語法錯誤,應以/[=]/替代;

6.4 布爾值

awk中,任何非0值或非空字符串都爲真,反之就爲假;

6.5 比較操做符:
x < y    True if x is less than y. 
x <= y    True if x is less than or equal to y. 
x > y    True if x is greater than y. 
x >= y    True if x is greater than or equal to y. 
x == y    True if x is equal to y. 
x != y    True if x is not equal to y. 
x ~ y    True if the string x matches the regexp denoted by y.   【y表明正則表達式模式PATTERN,x字符串能被模式y匹配到則爲真,不然爲假】
x !~ y    True if the string x does not match the regexp denoted by y. 
subscript in array      True if the array array has an element with the subscript subscript.【在指定的數組中有此元素下標,則爲真,不然爲假】

6.7 表達式間的邏輯關係符:
&&
||

6.8 條件表達式:
selector?if-true-exp:if-false-exp
至關於:
if selector; then
  if-true-exp
else
  if-false-exp
fi


舉例:
a=3
b=4
a>b?a is max:b ia max

6.9 函數調用:
function_name (para1,para2)

、





awk格式回顧:
awk [options] 'PATTERN { action }' file1 file2, ...


七 awk的模式:

awk 'program' input-file1 input-file2 ...
其中的program爲:
pattern { action }
pattern { action }
...

7.1 常見的模式類型:
1、Regexp: 正則表達式,格式爲/regular expression/
2、expresssion: 表達式,其值非0或爲非空字符時知足條件,如:$1 ~ /foo/ 或 $1 == "magedu",用運算符~(匹配)和!~(不匹配)。【各類邏輯表達式均可以應用】
3、Ranges: 指定的匹配範圍,格式爲pat1,pat2
4、BEGIN/END:特殊模式,僅在awk命令執行前運行一次或結束前運行一次
5、Empty(空模式):匹配任意輸入行;


1、Regexp: 正則表達式,格式爲/regular expression/
例:只處理/etc/passwd中以r開頭的用戶名:# awk -F: '/^r/{print $1}' /etc/passwd
root
rpc
rpcuser


2、expresssion: 表達式,其值非0或爲非空字符時知足條件,如:$1 ~ /foo/ 或 $1 == "magedu",用運算符~(匹配)和!~(不匹配)。【各類邏輯表達式均可以應用】
例:
查看剩餘內存:
free -m|awk 'NR==3{print $NF}'  

顯示用戶ID大於500的用戶名和ID號:# awk -F: '$3>=500{print $1,$3}' /etc/passwd
nfsnobody 65534
whitesky 500
hadoop 501
whitesmb 502
擴展:
[root@whiteskpc myscript]# awk -F: '$3-1>=500{print $1,$3}' /etc/passwd 【由此可知,直接使用算術運算來比較也徹底能夠,只要表達式支持的均可以】
nfsnobody 65534
hadoop 501
whitesmb 502

例:顯示默認shell爲bash的用戶:
# awk -F: '/bash$/{print $1,$7}' /etc/passwd【# awk -F: '$7~"bash$"{print $1,$7}' /etc/passwd ,此種寫法也可】
root /bin/bash
whitesky /bin/bash
hadoop /bin/bash
whitesmb /bin/bash
mysql /bin/bash
非bash的用戶:# awk -F: '$7!~"bash$"{print $1,$7}' /etc/passwd

                    
3、Ranges: 指定的匹配範圍,格式爲pat1,pat2
例:
[root@whiteskpc myscript]# awk -F: '$3==0,$7~"nologin"{print $1,$3,$7}' /etc/passwd
root 0 /bin/bash
bin 1 /sbin/nologin


4、BEGIN/END:特殊模式,僅在awk命令執行前運行一次或結束前運行一次
例:
在awk執行以前加一個標題
# awk -F: 'BEGIN{print "Username  ID       Shell"}{printf "%-10s%-10s%-20s\n",$1,$3,$7}' /etc/passwd 【注意BEGIN的位置】
Username  ID       Shell
root      0         /bin/bash           
bin       1         /sbin/nologin       
daemon    2         /sbin/nologin       
adm       3         /sbin/nologin    
結尾加標示:
# awk -F: 'BEGIN{print "Username  ID       Shell"}END{print "end of report"}{printf "%-10s%-10s%-20s\n",$1,$3,$7}' /etc/passwd


5、Empty(空模式):匹配任意輸入行;
# awk -F: '{printf "%-10s%-10s%-20s\n",$1,$3,$7}' /etc/passwd





7.2 常見的Action
1、Expressions:      【賦值、判斷等表達式】
2、Control statements     【控制語句,whilefordo while三個循環,if、case條件判斷語句,還能夠自定義函數】   
3、Compound statements     【複合語句】
4、Input statements     【重定向輸入】
5、Output statements    


/正則表達式/:使用通配符的擴展集。

關係表達式:能夠用下面運算符表中的關係運算符進行操做,能夠是字符串或數字的比較,如$2>%1選擇第二個字段比第一個字段長的行。

模式匹配表達式:

模式,模式:指定一個行的範圍。該語法不能包括BEGIN和END模式。

BEGIN:讓用戶指定在第一條輸入記錄被處理以前所發生的動做,一般可在這裏設置全局變量。

END:讓用戶在最後一條輸入記錄被讀取以後發生的動做。





八 控制語句:
8.1 if-else
語法:
單分支:if (condition) {then-body}
雙分支:
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 【printf 格式化打印】
awk -F: -v sum=0 '{if ($3>=500) sum++}END{print sum}' /etc/passwd        【使用了空模式,不作過濾】

8.2 while            【對一個字段作單獨處理,循環遍歷每個字段,意義不大】
語法: while (condition){statement1; statment2; ...}
awk -F: '{i=1;while (i<=3) {print $i;i++}}' /etc/passwd
例:打印passwd中每一行中大於等於四個字符的字串:
awk -F: '{i=1;while (i<=NF) { if (length($i)>=4) {print $i}; i++ }}' /etc/passwd

 
8.3 do-while
語法: do {statement1, statement2, ...} while (condition)
awk -F: '{i=1;do {print $i;i++}while(i<=3)}' /etc/passwd

8.4 for
語法: for ( variable assignment; condition; iteration process) { statement1, statement2, ...}
awk -F: '{for(i=1;i<=3;i++) print $i}' /etc/passwd
例:打印passwd中每一行中大於等於四個字符的字串:
awk -F: '{for(i=1;i<=NF;i++) { if (length($i)>=4) {print $i}}}' /etc/passwd

for循環還能夠用來遍歷數組元素:
語法: for (i in array) {statement1, statement2, ...}
awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A,BASH[A]}}' /etc/passwd

8.5 case
語法:switch (expression) { case VALUE or /REGEXP/: statement1, statement2,... default: statement1, ...}

8.6 break 和 continue
經常使用於循環或case語句中

8.7 next
提早結束對本行文本的處理,並接着處理下一行;例如,下面的命令將顯示其ID號爲奇數的用戶:
# awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd


九 awk中使用數組

9.1 數組

舉例:統計當前主機上每個TCP鏈接狀態以及每種鏈接狀態的數目【很是實用】
# netstat -tan | awk '/^tcp/{STATE[$NF]++}END{for (S in STATE) {print S,STATE[S]}}'  注:單引號內的都是PARTTEN,此句沒有ACTION【定義數組、變量儘可能大寫,小寫也不錯】
LISTEN 11
ESTABLISHED 1
解釋: 最後一列元素$NF做爲數組的下標,數組的元素是數字



array[index-expression]

index-expression可使用任意字符串;須要注意的是,若是某數據組元素事先不存在,那麼在引用其時,awk會自動建立此元素並初始化爲空串;所以,要判斷某數據組中是否存在某元素,須要使用index in array的方式。

要遍歷數組中的每個元素,須要使用以下的特殊結構:
for (var in array) { statement1, ... }
其中,var用於引用數組下標,而不是元素值;

例子:
netstat -ant | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
每出現一被/^tcp/模式匹配到的行,數組S[$NF]就加1,NF爲當前匹配到的行的最後一個字段,此處用其值作爲數組S的元素索引;

awk '{counts[$1]++}; END {for(url in counts) print counts[url], url}' /var/log/httpd/access_log
用法與上一個例子相同,用於統計某日誌文件中IP地的訪問量



9.2 刪除數組變量

從關係數組中刪除數組索引須要使用delete命令。使用格式爲:

delete  array[index]



10、awk的內置函數

split(string, array [, fieldsep [, seps ] ])
功能:將string表示的字符串以fieldsep爲分隔符進行分隔,並將分隔後的結果保存至array爲名的數組中;數組下標爲從0開始的序列;

netstat -ant | awk '/:80\>/{split($5,clients,":");IP[clients[1]]++}END{for(i in IP){print IP[i],i}}' | sort -rn | head -50

length([string])
功能:返回string字符串中字符的個數;


substr(string, start [, length])
功能:取string字符串中的子串,從start開始,取length個;start從1開始計數;

system(command)
功能:執行系統command並將結果返回至awk命令

systime()
功能:取系統當前時間

tolower(s)
功能:將s中的全部字母轉爲小寫

toupper(s)
功能:將s中的全部字母轉爲大寫

11、用戶自定義函數

自定義函數使用function關鍵字。格式以下:

function F_NAME([variable])
{
    statements
}

函數還可使用return語句返回值,格式爲「return value」。
相關文章
相關標籤/搜索