數據工程師常用的 Shell 命令

導讀:Linux以其強大的命令行稱霸江湖,Shell命令是數據極客的必修兵器。探索性數據分析,在需求和數據都不太明確的環境下,使用各種命令進行一次探索與挖掘。從基礎的文件查看到簡單的統計,再到一些常用的探索性分析命令,其目的都只是爲了更好的做數據分析與挖掘而已。


01 Shell命令行


對於經常和數據打交道的人來說,數據工程師應該也是常常和Linux打交道。Linux以其強大的命令行稱霸江湖,因此,Shell命令也是數據極客的必修兵器。


利用Linux命令行的幾個命令,就可以完成一些簡單的統計分析工作,比如利用wc命令統計文件行,單詞數,字符數,利用sort排序和去重,再結合uniq可以進行詞頻統計。比如:


$ cat file.txt

yunjie

yunjie-talk

yunjie-yun

yunjie

yunjie-shuo

$ sort file.txt | uniq -c | sort -nr | head -5

   2 yunjie

   1 yunjie-shuo

   1 yunjie-talk

   1 yunjie-yun


先用cat命令,瞭解一下文件的大概格式與內容,發現每行爲一個單詞。現在需要統計這些單詞出現的頻率,以及顯示出現次數最多的5個單詞。


先對文件進行排序,這樣相同的單詞在緊挨着的行,再後uniq -c 命令,統計不同的單詞及各個單詞出現的次數。這樣得到的結果就是次數後面緊接着單詞,然後使用sort -nr對次數進行排序,並逆序顯示,最後head命令顯示結果的前5行。


非常簡單的一種方式,讀取文件,排序,統計,再對統計結果進行逆序,最後只顯示前幾個結果。


類似於sql語句:


select word,count(1) cnt

from file

group by word

order by cnt desc

limit 5;


如果對sql語句熟悉的話,上面的形式應該更容易理解。雖然實現的思想和方式非常簡單,但在實際的探索性數據分析中使用卻非常頻繁。


02 探索性分析


比如在日誌分析中,有時並沒有非常明確的目標,或者即使有明確的目標,通常各種數據也並沒有明確的定義。比如,別人丟給你一個壓縮文件,說想分析一下里面有哪些是異常的訪問請求。任務描述就是這樣,沒有更明確的了。


拿到日誌文件和這樣的分析任務,就需要進行各種可能的探索性分析。先看一下文件的格式,是否壓縮過,使用gzip壓縮還是tar壓縮。解壓後,需要先大概瞭解一下,文件是什麼樣的格式。對於網絡請求的日誌文件,是一行一個請求和響應,還是多行一個請求和響應。查看文件有多少行,查看文件佔用空間大小。如果解壓後包含多個目錄或者文件,同樣的一個命令,更能發揮強大效果。此時,通常需要如下命令:


gzip/tar:壓縮/解壓

cat/zcat:文件查看

less/more:文件查看,支持gz壓縮格式直接查看

head/tail:查看文件前/後10行

wc:統計行數、單詞數、字符數

du -h -c -s:查看空間佔用


上面有一個比較有趣的命令組,less和more,這兩個都可以分頁查看文件。最開始有的more命令,好像是當時more不支持向後翻頁。於是一幫人就在此基礎上進行了改進,直接叫less,和more同樣的功能只是更強大些。因此,也發展出了“less is more”的哲學,“少即是多”,而且少比多更好。這種思想,在產品設計與代碼優化中都有體現。


瞭解文件的大概信息後,可能需要提取一行中某個字段的內容,或者需要搜索某些行出來,或者需要對某些字符或者行進行一定的修改操作,或者需要在衆多的目錄和文件中找出某此天的日誌(甚至找到後需要對這些天的日誌進行統一處理),此時下面這些命令可以幫你:


awk:命令行下的數據庫操作工具

join/cut/paste:關聯文件/切分字段/合併文件

fgrep/grep/egrep:全局正則表達式查找

find:查找文件,並且對查找結果批量化執行任務

sed:流編輯器,批量修改、替換文件

split:對大文件進行切分處理,按多少行一個文件,或者多少字節一個文件

rename:批量重命名(Ubuntu上帶的perl腳本,其它系統需要安裝),使用-n命令進行測試


如:


# 解壓縮日誌

$ gzip -d a.gz

$ tar zcvf/jcvf one.tar.bz2 one

# 直接查看壓縮日誌

$ less a.gz  

# 無需先解壓


另外,以z開頭的幾個命令可以簡單處理gzip壓縮文件, 如zcat:直接打印壓縮文件,還有zgrep/zfgrep/zegrep,在壓縮文件中直接查找。


# 查詢字符串,並顯示匹配行的前3行和後3行內容

fgrep 'yunjie-talk' -A 3 -B 3 log.txt

# 在當前目前(及子目錄)下,所有的log文件中搜索字符串hacked by:

$ find . -name "*.log" | xargs fgrep "hacked by"


fgrep, grep, egrep的一些區別:


fgrep按字符串的本來意思完全匹配,裏面的正則元字符當成普通字符解析, 如: fgrep “1.2.3.4″ 則只匹配ip地址: 1.2.3.4, 其中的.不會匹配任意字符。fgrep當然會比grep快多了。寫起來又簡單,不用轉義。

grep只使用普通的一些正則,egrep或者grep -E使用擴展的正則,如


egrep "one|two", 匹配one或者two

grep -E -v ".jpg|.png|.gif|.css|.js" log.txt |wc -l


查找所有來自日本的ip的請求,先把所有來源ip取出來,去重,找出日本的ip,放入文件japan.ip,再使用命令:


$ cat log.gz | gzip -d | fgrep -f japan.ip > japan.log


對hive中導出的文件,替換01


cat 0000* | sed 's/x1/ /g' > log.txt


03 其它常用命令


如果文件編碼是從windows上傳過來的gb2312編碼,需要處理成utf8的編碼,或者某個日誌被黑客後來修改過了,需要和原來的備份數據進行對比,這些工作都是需要數據工程師自己能熟悉的掌握。


假如日誌文件是最近一年的請求日誌,那麼可能是按天或者按小時進行單獨存放,此時如果只需要提取某些天(比如週末)的數據,很可能需要處理時間。


因此,下面的一些命令或者工具就很有用了:


date:命令行時間操作函數

sort/uniq:排序、去重、統計

comm:對兩個排序文件進行按行比較(共同行、只出現在左邊文件、只出現在右邊文件)

diff:逐字符比較文件的異同,配合cdiff,類似於github的顯示效果

curl/w3m/httpie:命令行下進行網絡請求

iconv:文件編碼轉換,如:iconv -f GB2312 -t UTF8 1.csv > 2.csv

seq:產生連續的序列,配合for循環使用


輸出今天/昨天的日期字符串


$ date -d today +%Y%m%d

20160320

$ date -d yesterday +%Y%m%d

20160319


對unix秒的處理


# 當前的時間

$ date +%s

1458484275

$date -d @1458484275

Sun Mar 20 22:31:15 CST 2016


兩個文件a.txt, b.txt求只出現在a.txt中的數據:


# 排序兩個文件

$ sort a.txt > a.txt.sort

$ sort b.txt > b.txt.sort

# 求只出現在c.sh中的內容

$ comm -2 -3 a.txt.sort b.txt.sort


04 批量操作


對上面的文件進行了一番探索分析後,可能已經有一定的線索或者眉目了,需要更進一步的處理大量的文件或者字段了。此時的步驟也許是一個消耗時間的過程,也許是一個需要看緣分的過程。總之,可能需要綜合上面的一些命令,並且對大量的日誌進行處理。


這也是體現Shell更強大的一面——批量化的功能了。命令比圖形界面的最大優勢就是,只需熟悉了,就很容易實現批量化操作,將這些批量化的命令組合成一個文件,於是便產生了腳本。


批量化命令或者腳本,熟悉幾個常用的流程控制,就能發揮出強大的性能:


if條件判斷:


if [ -d ${base_d} ];

    then mkdir -p ${base_d};

fi


while循環:


while

do

    do_something;

done


for循環(用得很多):


for x in *.log.gz;

do

    gzip -d ${x};

done


這幾個條件判斷與循環,也可以直接在命令行下使用,區別是多加幾個分號隔開即可。


另外,執行長時間的任務,最好直接用nohup來操作。


生成過去8天的日期序列:


$for num in `seq 8 -1 1`;do dd=`date --date="${num} day ago" +%Y%m%d`;echo ${dd};done

20160312

20160313

20160314

20160315

20160316

20160317

20160318

20160319


有目錄和文件如下:


20160320 目錄

    10.1.0.1_20160320*.log.gz   目錄

        201603200000.log.gz          文件

        201603200010.log.gz          文件

    10.1.0.2_20160320*.log.gz   目錄

        201603200000.log.gz         文件

        201603200010.log.gz         文件


需求:去掉目錄中的*.log.gz,這樣很容易讓人誤解爲文件。 rename -n爲測試,rename使用和sed相同的語法。


$ for d in 201603??;do echo ${d}; cd ${d}; rename -n 's/*.log.gz//' *.log.gz ; cd ..;done


測試完成後,使用rename不加-n爲真正執行重命名操作。


05 結尾


這兒只是簡單列舉了一些數據分析或者數據處理相關的命令,只能算是Linux的Shell那博大精深的命令中的冰山一角。


但如果能把這些相關的命令融會貫通,並且能實際使用的話,也算是在數據極客之路上多走了一步。


從基礎的文件查看到簡單的統計,再到一些常用的探索性分析命令,其目的都只是爲了更好的做數據分析與挖掘而已。能綜合這些命令,並組合起來使用,將命令存放到文件,即產生了Shell腳本。Shell腳本本身也是一門強大的學問了,其中各個命令還有每個命令支持的參數,值得慢慢研究。

發佈了12 篇原創文章 · 獲贊 23 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章