數據工程師,常用Shell命令

hmld6595 8年前發布 | 29K 次閱讀

來自:文/云戒(簡書作者)

原文鏈接:http://www.jianshu.com/p/1ea90c81b659

摘要: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) cntfrom file group by wordorder 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或者twogrep -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中導出的文件,替換\001

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 +%s1458484275 $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 < file.list

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};done20160312 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腳本本身也是一門強大的學問了,其中各個命令還有每個命令支持的參數,值得慢慢研究。

 本文由用戶 hmld6595 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!