因爲最近的工做內容的關係, 常常須要對文本文件作一些處理. 每次都要寫個腳原本處理實在是有點麻煩. 這時候想起來好久之前稍微接觸過的AWK, 來作這個工做真的是再合適不過了.python
所以, 趁着這個機會, 把AWK深刻學習一點,記錄在此.linux
AWK是一門解釋型的編程語言。在文本處理領域它是很是強大的,它的名字來源於它的三位做者的姓氏:Alfred Aho, Peter Weinberger 和 Brian Kernighan。正則表達式
GNU/Linux發佈的AWK目前由自由軟件基金會(FSF)進行開發和維護,一般也稱它爲 GNU AWK。shell
awk在下列任務中都有很是不錯的發揮, 本文後續也會舉不少示例.編程
簡單來講awk就是把文件逐行的讀入,以空格爲默認分隔符將每行切片,切開的部分再進行各類分析處理。微信
你能夠將其理解爲一個linux命令,只是使用參數以及方法多樣一些. 由於咱們常常會在命令行直接使用它.編程語言
你也能夠將其理解爲一個簡易的腳本語言, 由於在使用過程當中咱們也能夠寫邏輯表達式等各類語句.函數
先來個熱場的示例.學習
已有一個文本文件,格式以下:url
前面的數字是熱度, 後面的字符串是搜索詞.
100 阿里巴巴
200 京東
300 淘寶
400 awk怎麼使用
複製代碼
咱們想計算, 熱度大於等300的詞的熱度, 在總熱度中的一個比例
雖然聽起來有點繞, 可是這是一個很是常見的需求, 對應到這個示例中咱們是想計算 (300 + 400 ) / ( 100 + 200 + 300 + 400), 此時咱們只能打開咱們的編譯器, 選擇一門語言以後開始寫代碼了. 其實不用.
把上面的文本內容放進 a.txt中,而後執行下面的shell命令便可, 你會看到預期之中的 0.7.
awk '{{if ($1 >= 300) {sub_sum +=$1}};sum += $1 }; END{ret = sub_sum * 1.0 / sum; print ret}' a.txt
複製代碼
這段腳本作了什麼事情呢?
怎麼樣, 是否是比寫其餘shell或者python腳本快多了?
接下來將進入學習時間, 咱們逐個知識點的學習,看完本文,你也能這麼花裏胡哨的解決文本處理問題~.
awk除了能夠在命令行執行以外, 還能夠寫成腳本文件進行執行.咱們大體的瞭解一下這個用法,以後不作詳細講解,以命令行用法爲主要內容. 由於文本的用戶和命令行大同小異.
首先,建立一個包含腳本內容的文本文件 test.awk
{print $1 }
複製代碼
而後咱們用命令行執行這個腳本文件.
awk -f command.awk marks.txt
複製代碼
這個實際上是至關於命令行直接執行的一個擴展, 當你寫的腳本十分複雜(不推薦),且須要多人合做或者共享的時候, 腳本文件會是一個不錯的選擇.
awk [options] file ...
複製代碼
把上面腳本文件語法中的內容寫到 options 便可.
上面所講的, 是 awk是什麼以及 怎麼在系統中使用awk,接下來的內容就是 awk自身的一些語法.
awk程序的思路是, 逐行處理一個文件.
那麼讓咱們想一下, 當咱們想要 處理一個文件的時候會須要作些什麼?
awk的程序結構也是如此.
BEGIN 語句塊
BEGIN {awk-commands}
複製代碼
BEGIN語句塊在程序開始的使用執行,它只執行一次,在這裏能夠初始化變量。BEGIN是AWK的關鍵字,所以它必須爲大寫,注意,這個語句塊是可選的。
BODY 語句塊
/pattern/ {awk-commands}
複製代碼
BODY語句塊中的命令會對輸入的每一行執行,咱們也能夠經過提供模式來控制這種行爲。注意,BODY語句塊沒有關鍵字。
END 語句塊
END {awk-commands}
複製代碼
END語句塊在程序的最後執行,END是AWK的關鍵字,所以必須爲大寫,它也是可選的。
因此一個添加了所有可選項的awk命令以下所示:
awk [options] 'BEGIN{};{};END{}' file.txt
複製代碼
awk對經常使用的操做符都有支持,且與c語言使用方法同樣.具體支持的操做符有:
awk支持流程控制, 好比在本文最前方的示例中咱們使用了if語句.
或者相似下面的if語句都是合法的.
awk 'BEGIN {
a = 30;
if (a==10)
print "a = 10";
else if (a == 20)
print "a = 20";
else if (a == 30)
print "a = 30";
}'
複製代碼
循環操做與其餘C系語言同樣,主要包括 for,whlie,do...while,break,continue 語句.
示例:
awk 'BEGIN {
sum = 0; for (i = 0; i < 20; ++i) {
sum += i; if (sum > 50) exit(10); else print "Sum =", sum
}
}
複製代碼
與內建變量相對應的, 也有一部分的內建函數.
awk 還提供了一些內置函數,好比:
內建函數還有一些其餘的, 具體能夠在使用時在 man awk
中查詢.
雖然我我的是不支持用awk來作這麼繁雜的編程工做的,可是awk支持咱們自定義函數而且調用. 語法規範以下:
function function_name(argument1, argument2, ...) {
function body
}
複製代碼
咱們能夠在一個awk腳本中放入一下內容, 而後執行它.
function main(){
print "function"
}
BEGIN {
main()
}
複製代碼
這裏會列出一些經常使用的,簡單的使用示例.
全部的示例都如下面的示例爲輸入進行運行.
1) Amit Physics 80
2) Rahul Maths 90
3) Shyam Biology 87
4) Kedar English 85
5) Hari History 89
複製代碼
打印某列或者字段
AWK能夠只打印輸入字段中的某些列。
$ awk '{print $3 "\t" $4}' marks.txt
Physics 80
Maths 90
Biology 87
English 85
History 89
複製代碼
在示例文本中,第三列包含了科目名,第四列則是得分,上面的例子中,咱們只打印出了這兩列,$3 和 $4 表明了輸入記錄中的第三和第四個字段。
打印全部的行
默認狀況下,AWK會打印出全部匹配模式的行
$ awk '/a/ {print $0}' marks.txt
2) Rahul Maths 90
3) Shyam Biology 87
4) Kedar English 85
5) Hari History 89
複製代碼
上述命令會判斷每一行中是否包含a,若是包含則打印該行,若是BODY部分缺失則默認會執行打印,所以,上述命令和下面這個是等價的
$ awk '/a/' marks.txt
複製代碼
打印匹配模式的列
當模式匹配成功時,默認狀況下AWK會打印該行,可是也可讓它只打印指定的字段。例如,下面的例子中,只會打印出匹配模式的第三和第四個字段。
$ awk '/a/ {print $3 "\t" $4}' marks.txt
Maths 90
Biology 87
English 85
History 89
複製代碼
任意順序打印列
$ awk '/a/ {print $4 "\t" $3}' marks.txt
90 Maths
87 Biology
85 English
89 History
複製代碼
統計匹配模式的行數
$ awk '/a/{++cnt} END {print "Count = ", cnt}' marks.txt
Count = 4
複製代碼
打印超過18個字符的行
$ awk 'length($0) > 18' marks.txt
3) Shyam Biology 87
4) Kedar English 85
複製代碼
查找history歷史中,最經常使用的10個命令
history | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head
複製代碼
過濾文件中重複行
awk '!x[$0]++' <file>
複製代碼
將一行長度超過 72 字符的行打印
awk 'length>72' file
複製代碼
查看最近哪些用戶使用系統
last | grep -v "^$" | awk '{ print $1 }' | sort -nr | uniq -c
複製代碼
計算文本中的數值的和
awk '{s+=$1} ENG {printf "%.0f", s}' /path/to/file
複製代碼
當你用的時候臨時有忘記的或者不肯定的,隨時能夠查看幫助命令.
man awk
複製代碼
完。
以上皆爲我的所思所得,若有錯誤歡迎評論區指正。
歡迎轉載,煩請署名並保留原文連接。
聯繫郵箱:huyanshi2580@gmail.com
更多學習筆記見我的博客或關注微信公衆號 <呼延十 >------>呼延十