awk、grep和sed被稱為linux三劍客,事實上grep和awk我在日常作業中也常用到(sed用的比較少),可能有些人對awk了解比較少,我先大概介紹下, 很多人以為awk只是一個文本處理工具,實際上他們也是這么用的,但事實上它其實是一門語言,擁有數學運算子、行程控制陳述句,甚至針對于文本處理封裝了很多內置變數和函式,這造就了它強大的文本處理能力, 如果grep只能做到資料的篩選,那awk還能做到資料的處理、分析甚至生成報表,畢竟它是一門完整的編程語言,
因為這篇文章不是awk的入門教程,如果想入門的話我推薦阮一峰老師的awk 入門教程 和 左耳朵耗子的AWK 簡明教程 ,
回到我今天的正題,今天我給大家看個我常使用awk的場景,因為做后端開發,經常在做資料分析的時候會有這樣的問題,1.面對幾十萬條的資料,需要篩選出幾百幾千個特定key的資料,2.對這幾百萬條資料,針對其中的id欄位補齊其他欄位,
這時候可能有精通excel的同學跳出來說 “就這,so easy,vlookup就搞定!” ,事實上,excel確實可以解決問題,但有點重,甚至有些時候我們在服務器上還用不了excel,還有啥其他方法?針對我說的這倆場景,其實仔細想一下,是不是sql中倆表join就能解決問題,實際上你并不需要真正把檔案灌到資料庫里,只需要用awk一條命令就能解決,
實體
我們把問題具像下,假設有兩個檔案,score.txt存著學號+成績的資料,另外一個name.txt存著學號+姓名的資料,你現在想知道每個人都烤了多少分,
score.txt
id score
1 87
2 67
3 68
4 75
5 90
6 100
7 0
name.txt
id name
1 張三
2 李四
3 王五
4 趙二
5 劉能
6 熊大
你想得到一份包含學號 姓名和成績的資料,就像下面這樣,
id score name
1 87 張三
2 67 李四
3 68 王五
4 75 趙二
5 90 劉能
6 100 熊大
7 0
用awk生成這樣的資料有多簡單?只需要一行代碼,你可以保存name.txt和score.txt,然后執行下面命令嘗試下,
awk 'ARGV[1]==FILENAME {map[$1]=$2} ARGV[2]==FILENAME {print $0, map[$1]}' name.txt score.txt
簡簡單單就實作了name.txt和score.txt在id之上的right join,
解釋下上面的代碼,ARGV和FILENAME是awk內置的變數,ARGV里存放在awk所接受的引數串列,像上面 ARGV[1]就是"name.txt",ARGV[2]就是"score.txt",awk是面向行的,所以針對每一行資料都會執行ARGV[1]==FILENAME {map[$1]=$2} ARGV[2]==FILENAME {print $0, map[$1]},每一行資料都會屬于某個檔案,FILENAME標識出當前行所屬的檔案名,像在括號{}前的ARGV[1]==FILENAME 你可以看做是其他語法中的條件判斷,你可以認為它就是省略了if,但和if的功能是一致的,
所以上述代碼的含義就是 如果當前行是輸入name.txt的,就把學號和姓名存在map里(awk里的變數不用預先宣告), 如果當前行是屬于score.txt,就從map里把姓名找出來,然后把資料輸出,
結語
awk 'ARGV[1]==FILENAME {map[$1]=$2} ARGV[2]==FILENAME {print $0, map[$1]}' name.txt score.txt
針對于不同的資料,只需要調整下$后面的具體值,可以實作用不同的列作為key來做join,其實這里并不比sql的join復雜,但在linux服務器上卻很方便,上網中我只是實作了right join,如果在print $0, map[$1]前加上if (length(map[$1]) > 0) 就可以實作inner join,left join的話也只需要把檔案名換一下,
知道了這些,awk實作多檔案的交集、差集等操作都不在話下,另外不要忘記了awk其實也是一門編程語言,所以它也可以實作很多很復雜的邏輯,你可以把代碼在某個檔案里然后用-f引數調起,比如我之前老師用awk做一些簡單的統計作業,比如計算均值、總和…… awk簡直堪稱后端工程師提效利器,
本文來自https://blog.csdn.net/xindoo
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/205842.html
標籤:其他
上一篇:并發編程 - 執行緒
