linux awk 的基礎應用

在Linux系統中,AWK 是一個非常強大的文本處理工具,在日常統計中起到重要的作用。

[@sjs_73_194 ~]$ man awk
GAWK(1)                        Utility Commands                        GAWK(1)

NAME
       gawk - pattern scanning and processing language

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

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

 

一、內置變量

屬 性 說 明
$0 當前記錄行,代表一行記錄
$1~$n 當前記錄的第n個字段,字段間由FS分隔
FS 輸入字段分隔符,默認是空格
NF 當前記錄中的字段個數,就是有多少列,一般取最後一列字段
NR 已經讀出的記錄數,就是行號,從1開始
RS 輸入的記錄分隔符,默認爲換行符
OFS 輸出字段分隔符,默是空格
ORS 輸出的記錄分隔符,默認爲換行符
ARGC 命令行參數個數
ARGV 命令行參數數組
FILENAME 當前輸入文件的名字
IGNORECASE 如果爲真,則進行忽略大小寫的匹配
ARGIND 當前被處理文件的ARGV標誌符
CONVFMT 數字轉換格式 %.6g
ENVIRON UNIX環境變量
ERRNO UNIX系統錯誤消息
FIELDWIDTHS 輸入字段寬度的空白分隔字符串
FNR 當前記錄數
OFMT 數字的輸出格式 %.6g
RSTART 被匹配函數匹配的字符串首
RLENGTH 被匹配函數匹配的字符串長度
SUBSEP \034

 

二、 變量實例

1) 常用操作

[@sjs_73_194 ~]$ awk '/^root/ {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[@sjs_73_194 ~]$

[@sjs_73_194 ~]$ awk '{if (match($0, /root/)) print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[@sjs_73_194 ~]$ 

2) FS 分隔符

[@sjs_73_194 ~]$ awk 'BEGIN{FS=":"} /^root/ {print $1,$NF}' /etc/passwd
root /bin/bash
[@sjs_73_194 ~]$ 

    注: FS爲字段分隔符,默認是空格。因爲passwd裏是”:”分隔,所以需要修改默認分隔符。除此之外還可以通過-F 來分隔,如

[@sjs_73_194 ~]$ awk -F: '/^root/ {print $1,$NF}' /etc/passwd               
root /bin/bash
[@sjs_73_194 ~]$ 

 

3) 記錄條數(NR,FNR)

[@sjs_73_194 ~]$ awk '{print NR, FNR}' /etc/passwd  
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
11 11
... ...

 

4) 字段分隔符(OFS)

awk 'BEGIN{FS=":"; OFS="##"} /^root/ {print FNR, $1, $NF}' /etc/passwd

結果: 1##root##/bin/bash

注: OFS設置默認字段分隔符, FNR當前記錄行

 

5) 行記錄分隔符(ORS)

awk 'BEGIN{FS=":"; ORS="##"}{print FNR, $1, $NF}' /etc/passwd

結果: 1 root /bin/bash##2 daemon /bin/sh##3 bin /bin/sh##4 sys /bin/sh##5 sync /bin/sync##......

 

awk 'BEGIN{FS=":"; ORS="\n"}{print FNR, $1, $NF}' /etc/passwd                  #    "/n" 是linux 中換行符

結果:

1 root /bin/bash
2 daemon /bin/sh
3 bin /bin/sh
4 sys /bin/sh
5 sync /bin/sync

.......

注:  ORS默認是換行符,這裏修改爲:”##”,所有行之間用”##”分隔了

 

6) 參數獲取(ARGC ,ARGV)

awk 'BEGIN{FS=":"; print "ARGC="ARGC; for(k in ARGV) {print k"="ARGV[k];}}' /etc/passwd

結果: 

ARGC=2
0=awk
1=/etc/passwd

注: ARGC得到所有輸入參數個數,ARGV獲得輸入參數內容是一個數組

 

7) 獲得傳入的文件名(FILENAME)

awk 'BEGIN{FS=":";}/^r/ {print FILENAME, "\t", $0}' /etc/passwd

結果:

/etc/passwd   root:x:0:0:root:/root:/bin/bash
/etc/passwd   rtkit:x:110:117:RealtimeKit,,,:/proc:/bin/false

注: FILENAME, $0-$N,NF 不能使用在BEGIN中,BEGIN中不能獲得任何與文件記錄操作的變量

 

8) 獲得linux環境變量(ENVIRON)

awk 'BEGIN{print ENVIRON["PATH"];}' /etc/passwd

結果: /home/homer/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

注:  ENVIRON是子典型數組,可以通過對應鍵值獲得它的值,linux 環境變量還有$HOME,$PWD等,可以通過linux 命令 env 查看

 

9) 輸出數據格式設置(OFMT)

awk 'BEGIN{OFMT="%.3f"; print 1, 2.0, 3.1, 2/3, 123.11111111;}' /etc/passwd

結果: 1    2    3.100    0.667    123.111

注: OFMT默認輸出格式是:%.6g 保留六位小數,這裏修改OFMT會修改默認數據輸出格式,如保留三位小數

 

10) 按寬度指定分隔符(FIELDWIDTHS)

echo 20130108122448 | awk 'BEGIN{FIELDWIDTHS="4 2 2 2 2 3"}{print $1"-"$2"-"$3, $4":"$5":"$6}'

結果: 2013-01-08 12:24:48

注: FIELDWIDTHS其格式爲空格分隔的一串數字,用以對記錄進行域的分隔,FIELDWIDTHS="4 2 2 2 2 2"就表示$1寬度是4,$2是2,$3是2 .... 這個時候會忽略FS分隔符

 

11) RSTART,RLENGTH使用

awk 'BEGIN{start=match("this is 1 teststr", /[a-z]+$/); print start, RSTART, RLENGTH }'

結果: 11 11 7

 

awk 'BEGIN{start=match("this is a test",/^[a-z ]+$/); print start, RSTART, RLENGTH }'

結果: 0 0 -1

 

awk 'BEGIN{start=match("this is a test",/^[a-z ]+$/); print start, RSTART, RLENGTH }'

結果: 1 1 14                 # 增加了一個空格“ ”匹配

注: RSTART 被匹配正則表達式首位置,RLENGTH 匹配字符長度,沒有找到爲-1

 

 

三、外部變量

1) 基本用法

awk 中兩個特別的表達式,BEGIN和END

這兩者都可用於pattern中,提供BEGIN和END的作用是給程序賦予 初始狀態 和 程序結束 之後執行一些掃尾的工作。

a) 任何在BEGIN之後列出的操作(在{}內),將在awk開始掃描輸入之前執行

b) 任何在END之後列出的操作,將在掃描完全部的輸入之後執行

因此,通常使用BEGIN來顯示變量和初始化變量,使用END來輸出最終結果。

示例: echo 'awk test' | awk 'BEGIN{print "start...."} {print $0} END{print "end...."}'

結果: 

start....
awk test
end....

 

2) 獲取外部變量

格式如: awk ‘{action}’ 變量名=變量值 ,這樣傳入變量可以在action中獲得值。

示例: 

test='awk test'

echo | awk  '{print test}' test="$test"

結果: awk test

 

echo | awk  test="$test" '{print test}'

結果: awk: cmd. line:1: fatal: cannot open file `{print test}' for reading (No such file or directory)

注:變量名與值放到’{action}’後面,即 test="$test" 在 print 後面

 

3) BEGIN程序塊中變量

格式如:awk –v 變量名=變量值 [–v 變量2=值2 …] 'BEGIN{action}’ 

示例:

test='awk test'

echo | awk -v test="$test" 'BEGIN{print test}'

結果: awk test

 

echo | awk -v test="$test" '{print test}'

結果: awk test

注:用-v 傳入變量,可以在3中類型的action 中都可以獲得到,但順序在 action前面

 

4) 外部環境變量

awk  'BEGIN{for (i in ENVIRON) {print i"="ENVIRON[i];}}'

結果:

HLVL=1
PWD=/home/homer
JAVA_HOME=/home/homer/eclipse/jdk1.7.0_05
SHELL=/bin/bash

PATH=/home/homer/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

..........

注:  ENVIRON是子典型數組,可以通過對應鍵值獲得它的值,linux 環境變量還有$HOME,$PWD等,可以通過linux 命令 env 查看

 

四、統計應用

1) match匹配

[@zw_37_232 scookie]# head tmp.log 
/cesu.gif?b2386=0&b2387=128
# 
[@zw_37_232 scookie]# awk '{match($0,/.+b2386=([^,]+)\&b2387=([^,]+)/,a);print a[1], a[2]}'  tmp.log      
0 128
[@zw_37_232 scookie]# 

2) 多個文件

NR:表示awk開始執行程序後所讀取的數據行數。
FNR:awk當前讀取的記錄數,其變量值小於等於NR(比如當讀取第二個文件時,FNR是從0開始重新計數,而NR不會)。

NR==FNR:用於在讀取兩個或兩個以上的文件時,判斷是不是在讀取第一個文件。

[@zw_37_232 cesu]# head -n 1 tmp.log 
710000 926
[@zw_37_232 cesu]# head -n 1 ../iploc.txt 

[@zw_37_232 cesu]# head -n 3 ../iploc.txt  

110000  北京市
[@zw_37_232 cesu]# awk 'NR==FNR{a[$1]=$2;next}{print $1,a[$1]}' ../iploc.txt tmp.log > sort.region.log
[@zw_37_232 cesu]# head -n 10 sort.region.log 
710000 臺灣省
650000 新疆維吾爾自治區
540000 西藏自治區
530000 雲南省
810000 香港特別行政區
650000 新疆維吾爾自治區
540000 西藏自治區
520000 貴州省
650000 新疆維吾爾自治區
650000 新疆維吾爾自治區

參考推薦: 

awk 實例 (IBM)

沉于思考,默默學習

linux awk 內置函數實例

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章