首頁 > 軟體

Linux awk命令使用詳述

2020-06-16 16:56:54

awk是一個強大的文字分析工具,相對於grep的查詢,sed的編輯,awk在其對資料分析並生成報告時,顯得尤為強大。簡單來說awk就是把檔案逐行的讀入,以空格為預設分隔符將每行切片,切開的部分再進行各種分析處理。

awk有3個不同版本: awk、nawk和gawk,未作特別說明,一般指gawk,gawk 是 AWK 的 GNU 版本。

awk其名稱得自於它的創始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母。實際上 AWK 的確擁有自己的語言: AWK 程式設計語言 , 三位建立者已將它正式定義為“樣式掃描和處理語言”。它允許您建立簡短的程式,這些程式讀取輸入檔案、為資料排序、處理資料、對輸入執行計算以及生成報表,還有無數其他的功能。

awk是一個強大的文字分析工具,相對於grep的查詢,sed的編輯,awk在其對資料分析並生成報告時,顯得尤為強大。簡單來說awk就是把檔案逐行的讀入,以空格為預設分隔符將每行切片,切開的部分再進行各種分析處理。

awk有3個不同版本號: awk、nawk和gawk,未作特別說明,一般指gawk。

awk程式的報告生成能力通經常使用來從大文字檔案裡提取資料元素並將它們格式化成可讀的報告。最完美的樣例是格式化紀錄檔檔案。

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@localhost profile.d]# ls -lh
total 136K
-rwxr-xr-x 1 root root  766 Jul 22  2011 colorls.csh
-rwxr-xr-x 1 root root  727 Jul 22  2011 colorls.sh
-rw-r--r-- 1 root root   92 Feb 23  2012 cvs.csh
-rwxr-xr-x 1 root root   78 Feb 23  2012 cvs.sh
-rwxr-xr-x 1 root root  192 Mar 25  2009 glib2.csh
-rwxr-xr-x 1 root root  192 Mar 25  2009 glib2.sh
-rw-r--r-- 1 root root  218 Jun  6  2013 krb5-devel.csh
-rw-r--r-- 1 root root  229 Jun  6  2013 krb5-devel.sh
-rw-r--r-- 1 root root  218 Jun  6  2013 krb5-workstation.csh
-rw-r--r-- 1 root root  229 Jun  6  2013 krb5-workstation.sh
-rwxr-xr-x 1 root root 3.0K Feb 22  2012 lang.csh
-rwxr-xr-x 1 root root 3.4K Feb 22  2012 lang.sh
-rwxr-xr-x 1 root root  122 Feb 23  2012 less.csh
-rwxr-xr-x 1 root root  108 Feb 23  2012 less.sh
-rwxr-xr-x 1 root root   97 Mar  6  2011 vim.csh
-rwxr-xr-x 1 root root  293 Mar  6  2011 vim.sh
-rwxr-xr-x 1 root root  170 Jan  7  2007 which-2.sh

試一下awk的使用

ls -lh | awk '{print $1}'

在這裡awk 後面沒有BEGIN和END,跟著的是pattern,也就是每一行都會經過這個命令,在awk中$n,表示第幾列,在這裡表示列印每一行的第一列。

  • $0 當前記錄(這個變數中存放著整個行的內容)
  • $1~$n 當前記錄的第n個欄位,欄位間由FS分隔
  • FS 輸入欄位分隔符 預設是空格或Tab
  • NF 當前記錄中的欄位個數,就是有多少列
  • NR 已經讀出的記錄數,就是行號,從1開始,如果有多個檔案話,這個值也是不斷累加中。
  • FNR 當前記錄數,與NR不同的是,這個值會是各個檔案自己的行號
  • RS 輸入的記錄分隔符, 預設為換行符
  • OFS 輸出欄位分隔符, 預設也是空格
  • ORS 輸出的記錄分隔符,預設為換行符
  • FILENAME 當前輸入檔案的名字

如列印每一行的行數:

[root@localhost profile.d]# ls -lh | awk '{print NR " " $1}'
1 total
2 -rwxr-xr-x
3 -rwxr-xr-x
4 -rw-r--r--
5 -rwxr-xr-x
6 -rwxr-xr-x
7 -rwxr-xr-x
8 -rw-r--r--
9 -rw-r--r--
10 -rw-r--r--
11 -rw-r--r--
12 -rwxr-xr-x
13 -rwxr-xr-x
14 -rwxr-xr-x
15 -rwxr-xr-x
16 -rwxr-xr-x
17 -rwxr-xr-x
18 -rwxr-xr-x

這樣再來看這段語句應該就很容易理解了:

root@Ubuntu:~# awk  -F ':'  '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%sn",FILENAME,NR,NF,$0)}' /etc/passwd
filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/usr/sbin/nologin
filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/usr/sbin/nologin
filename:/etc/passwd,linenumber:5,columns:7,linecontent:sync:x:4:65534:sync:/bin:/bin/sync
filename:/etc/passwd,linenumber:6,columns:7,linecontent:games:x:5:60:games:/usr/games:/usr/sbin/nologin

變數

除了awk的內建變數,awk還可以自定義變數。

如下引入變數sum,統計py檔案的大小:

root@ubuntu:~# ls -l  *.py | awk '{sum+=$5} END {print sum}'
574

語句

awk中的條件語句是從C語言中借鑑來的,見如下宣告方式:

if語句

if (expression) {
    statement;
    statement;
    ... ...
}

if (expression) {
    statement;
} else {
    statement2;
}

if (expression) {
    statement1;
} else if (expression1) {
    statement2;
} else {
    statement3;
}

迴圈語句

awk中的迴圈語句同樣借鑒於C語言,支援while、do/while、for、break、continue,這些關鍵字的語意和C語言中的語意完全相同。

陣列

因為awk中陣列的下標可以是數位和字母,陣列的下標通常被稱為關鍵字(key)。值和關鍵字都儲存在內部的一張針對key/value應用hash的表格裡。由於hash不是順序儲存,因此在顯示陣列內容時會發現,它們並不是按照你預料的順序顯示出來的。陣列和變數一樣,都是在使用時自動建立的,awk也同樣會自動判斷其儲存的是數位還是字串。一般而言,awk中的陣列用來從記錄中收集資訊,可以用於計算總和、統計單詞以及跟蹤模板被匹配的次數等等。

使用陣列,統計重複出現的次數:

[root@localhost cc]# cat test.txt
a 00
b 01
c 00
d 02
[root@localhost cc]# awk '{sum[$2]+=1}END{for(i in sum)print i"t"sum[i]}' test.txt
00 2
01 1
02 1

站點紀錄檔分析

以下使用Linux中的Awk對tomcat中紀錄檔檔案做一些分析,主要統計pv,uv等。

紀錄檔文名稱:access_2013_05_30.log,大小57.7 MB 。

這次分析僅僅是簡單演示,所以不是太精確地處理資料。

紀錄檔地址:http://download.csdn.net/detail/u011204847/9496357

紀錄檔資料演示樣例:

紀錄檔總行數:

列印的第七列資料為紀錄檔的URL:

分析中用到的一些知識:

  • shell中的管道|
    command 1 | command 2 #他的功能是把第一個命令command 1執行的結果作為command 2的輸入傳給command 2

  • wc -l #統計行數

  • uniq -c #在輸出行前面加上每行在輸入檔案裡出現的次數

  • uniq -u #僅顯示不反復的行

  • sort -nr
    -n:按照數值的大小排序
    -r:以相反的順序來排序
    -k:按照哪一列進行排序

  • head -3 #取前三名

資料淨化:

1、第一次清洗:去除URL中以/static/開頭的URL

awk '($7 !~ /^/static//){print $0}' access_2013_05_30.log > clean_2013_05_30.log

去除前:

去除後:

2、第二次清洗:去除圖片、css和js

awk '($7 !~ /.jpg|.png|.jpeg|.gif|.css|.js/) {print $0}' clean_2013_05_30.log > clean2_201 3_05_30.log

PV

pv是指網頁訪問次數

方法:統計全部資料的總行數

資料淨化:對原始資料中的干擾資料進行過濾

awk 'BEGIN{pv=0}{pv++}END{print "pv:"pv}' clean2_2013_05_30.log > pv_2013_05_30

UV

uv指的是訪問人數。也就是獨立IP數

對ip反復的資料進行去重,然後再統計全部行數

awk '{print $1}' clean2_2013_05_30.log |sort -n |uniq -u |wc -l > uv_2013_05_30

訪問最多的IP(前10名)

對ip反復的資料進行去重的時候還要彙總,取前10名

awk '{print $1}' clean2_2013_05_30.log | sort -n | uniq -c |sort -nr -k 1|head -10 > top10_2013_05_30

訪問前十的URL(能夠用來分析站點哪個模組最受歡迎)

awk '{print $7}' clean2_2013_05_30.log | sort | uniq -c |sort -nr -k 1|head -10 > top10URL_2013_ 05_30

本文永久更新連結地址http://www.linuxidc.com/Linux/2018-01/150361.htm


IT145.com E-mail:sddin#qq.com