摘要:Linux以其強(qiáng)大的命令行稱霸江湖,Shell命令是數(shù)據(jù)極客的必修兵器站楚。探索性數(shù)據(jù)分析脱惰,在需求和數(shù)據(jù)都不太明確的環(huán)境下,使用各種命令進(jìn)行一次探索與挖掘窿春。從基礎(chǔ)的文件查看到簡(jiǎn)單的統(tǒng)計(jì)拉一,再到一些常用的探索性分析命令采盒,其目的都只是為了更好的做數(shù)據(jù)分析與挖掘而已。
01 Shell命令行
對(duì)于經(jīng)常和數(shù)據(jù)打交道的人來說蔚润,數(shù)據(jù)工程師應(yīng)該也是常常和Linux打交道磅氨。Linux以其強(qiáng)大的命令行稱霸江湖,因此嫡纠,Shell命令也是數(shù)據(jù)極客的必修兵器烦租。
利用Linux命令行的幾個(gè)命令,就可以完成一些簡(jiǎn)單的統(tǒng)計(jì)分析工作除盏,比如
利用wc命令統(tǒng)計(jì)文件行叉橱,單詞數(shù),字符數(shù)者蠕,利用sort排序和去重窃祝,再結(jié)合uniq可以進(jìn)行詞頻統(tǒng)計(jì)。比如:
$ 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命令踱侣,了解一下文件的大概格式與內(nèi)容粪小,發(fā)現(xiàn)每行為一個(gè)單詞。現(xiàn)在需要統(tǒng)計(jì)這些單詞出現(xiàn)的頻率泻仙,以及顯示出現(xiàn)次數(shù)最多的5個(gè)單詞糕再。
先對(duì)文件進(jìn)行排序量没,這樣相同的單詞在緊挨著的行玉转,再后uniq -c 命令,統(tǒng)計(jì)不同的單詞及各個(gè)單詞出現(xiàn)的次數(shù)殴蹄。這樣得到的結(jié)果就是次數(shù)后面緊接著單詞究抓,然后使用sort -nr對(duì)次數(shù)進(jìn)行排序,并逆序顯示袭灯,最后head命令顯示結(jié)果的前5行刺下。
非常簡(jiǎn)單的一種方式,讀取文件稽荧,排序橘茉,統(tǒng)計(jì),再對(duì)統(tǒng)計(jì)結(jié)果進(jìn)行逆序姨丈,最后只顯示前幾個(gè)結(jié)果畅卓。
類似于sql語句:
select word,count(1) cnt
from file
group by word
order by cnt desc
limit 5;
如果對(duì)sql語句熟悉的話,上面的形式應(yīng)該更容易理解蟋恬。雖然實(shí)現(xiàn)的思想和方式非常簡(jiǎn)單翁潘,但在實(shí)際的探索性數(shù)據(jù)分析中使用卻非常頻繁。
02 探索性分析
比如在日志分析中歼争,有時(shí)并沒有非常明確的目標(biāo)拜马,或者即使有明確的目標(biāo)渗勘,通常各種數(shù)據(jù)也并沒有明確的定義。比如俩莽,別人丟給你一個(gè)壓縮文件旺坠,說想分析一下里面有哪些是異常的訪問請(qǐng)求。任務(wù)描述就是這樣豹绪,沒有更明確的了价淌。
拿到日志文件和這樣的分析任務(wù),就需要進(jìn)行各種可能的探索性分析瞒津。先看一下文件的格式蝉衣,是否壓縮過,使用gzip壓縮還是tar壓縮巷蚪。解壓后病毡,需要先大概了解一下,文件是什么樣的格式屁柏。對(duì)于網(wǎng)絡(luò)請(qǐng)求的日志文件啦膜,是一行一個(gè)請(qǐng)求和響應(yīng),還是多行一個(gè)請(qǐng)求和響應(yīng)淌喻。查看文件有多少行僧家,查看文件占用空間大小。如果解壓后包含多個(gè)目錄或者文件裸删,同樣的一個(gè)命令八拱,更能發(fā)揮強(qiáng)大效果。此時(shí)涯塔,通常需要如下命令:
gzip/tar:壓縮/解壓
cat/zcat:文件查看
less/more:文件查看肌稻,支持gz壓縮格式直接查看
head/tail:查看文件前/后10行
wc:統(tǒng)計(jì)行數(shù)、單詞數(shù)匕荸、字符數(shù)
du -h -c -s:查看空間占用
上面有一個(gè)比較有趣的命令組爹谭,less和more,這兩個(gè)都可以分頁查看文件榛搔。最開始有的more命令诺凡,好像是當(dāng)時(shí)more不支持向后翻頁。于是一幫人就在此基礎(chǔ)上進(jìn)行了改進(jìn)践惑,直接叫l(wèi)ess腹泌,和more同樣的功能只是更強(qiáng)大些。因此童本,也發(fā)展出了“l(fā)ess is more"的哲學(xué)真屯,“少即是多”,而且少比多更好穷娱。這種思想绑蔫,在產(chǎn)品設(shè)計(jì)與代碼優(yōu)化中都有體現(xiàn)运沦。
了解文件的大概信息后,可能需要提取一行中某個(gè)字段的內(nèi)容配深,或者需要搜索某些行出來携添,或者需要對(duì)某些字符或者行進(jìn)行一定的修改操作,或者需要在眾多的目錄和文件中找出某此天的日志(甚至找到后需要對(duì)這些天的日志進(jìn)行統(tǒng)一處理)篓叶,此時(shí)下面這些命令可以幫你:
awk:命令行下的數(shù)據(jù)庫操作工具
join/cut/paste:關(guān)聯(lián)文件/切分字段/合并文件
fgrep/grep/egrep:全局正則表達(dá)式查找
find:查找文件烈掠,并且對(duì)查找結(jié)果批量化執(zhí)行任務(wù)
sed:流編輯器,批量修改缸托、替換文件
split:對(duì)大文件進(jìn)行切分處理左敌,按多少行一個(gè)文件,或者多少字節(jié)一個(gè)文件
rename:批量重命名(Ubuntu上帶的perl腳本俐镐,其它系統(tǒng)需要安裝)矫限,使用-n命令進(jìn)行測(cè)試
如:
# 解壓縮日志
$ gzip -d a.gz
$ tar zcvf/jcvf one.tar.bz2 one
# 直接查看壓縮日志
$ less a.gz # 無需先解壓
另外,以z開頭的幾個(gè)命令可以簡(jiǎn)單處理gzip壓縮文件, 如zcat:直接打印壓縮文件佩抹,還有zgrep/zfgrep/zegrep叼风,在壓縮文件中直接查找。
# 查詢字符串棍苹,并顯示匹配行的前3行和后3行內(nèi)容
fgrep 'yunjie-talk' -A 3 -B 3 log.txt
# 在當(dāng)前目前(及子目錄)下无宿,所有的log文件中搜索字符串hacked by:
$ find . -name "*.log" | xargs fgrep "hacked by"
fgrep, grep, egrep的一些區(qū)別:
fgrep按字符串的本來意思完全匹配,里面的正則元字符當(dāng)成普通字符解析枢里, 如: fgrep "1.2.3.4" 則只匹配ip地址: 1.2.3.4, 其中的.不會(huì)匹配任意字符孽鸡。fgrep當(dāng)然會(huì)比grep快多了。寫起來又簡(jiǎn)單坡垫,不用轉(zhuǎn)義梭灿。
grep只使用普通的一些正則画侣,egrep或者grep -E使用擴(kuò)展的正則冰悠,如
egrep "one|two", 匹配one或者two
grep -E -v "\.jpg|\.png|\.gif|\.css|.js" log.txt |wc -l
查找所有來自日本的ip的請(qǐng)求,先把所有來源ip取出來配乱,去重溉卓,找出日本的ip,放入文件japan.ip搬泥,再使用命令:
$ cat log.gz | gzip -d | fgrep -f japan.ip > japan.log
對(duì)hive中導(dǎo)出的文件桑寨,替換\001
cat 0000* | sed 's/\x1/ /g' > log.txt
03 其它常用命令
如果文件編碼是從windows上傳過來的gb2312編碼,需要處理成utf8的編碼忿檩,或者某個(gè)日志被黑客后來修改過了尉尾,需要和原來的備份數(shù)據(jù)進(jìn)行對(duì)比,這些工作都是需要數(shù)據(jù)工程師自己能熟悉的掌握燥透。
假如日志文件是最近一年的請(qǐng)求日志沙咏,那么可能是按天或者按小時(shí)進(jìn)行單獨(dú)存放辨图,此時(shí)如果只需要提取某些天(比如周末)的數(shù)據(jù),很可能需要處理時(shí)間肢藐。
因此故河,下面的一些命令或者工具就很有用了:
date:命令行時(shí)間操作函數(shù)
sort/uniq:排序、去重吆豹、統(tǒng)計(jì)
comm:對(duì)兩個(gè)排序文件進(jìn)行按行比較(共同行鱼的、只出現(xiàn)在左邊文件、只出現(xiàn)在右邊文件)
diff:逐字符比較文件的異同痘煤,配合cdiff凑阶,類似于github的顯示效果
curl/w3m/httpie:命令行下進(jìn)行網(wǎng)絡(luò)請(qǐng)求
iconv:文件編碼轉(zhuǎn)換,如:iconv -f GB2312 -t UTF8 1.csv > 2.csv
seq:產(chǎn)生連續(xù)的序列衷快,配合for循環(huán)使用
輸出今天/昨天的日期字符串
$ date -d today +%Y%m%d
20160320
$ date -d yesterday +%Y%m%d
20160319
對(duì)unix秒的處理
# 當(dāng)前的時(shí)間
$ date +%s
1458484275
$date -d @1458484275
Sun Mar 20 22:31:15 CST 2016
兩個(gè)文件a.txt, b.txt求只出現(xiàn)在a.txt中的數(shù)據(jù):
# 排序兩個(gè)文件
$ sort a.txt > a.txt.sort
$ sort b.txt > b.txt.sort
# 求只出現(xiàn)在c.sh中的內(nèi)容
$ comm -2 -3 a.txt.sort b.txt.sort
04 批量操作
對(duì)上面的文件進(jìn)行了一番探索分析后晌砾,可能已經(jīng)有一定的線索或者眉目了,需要更進(jìn)一步的處理大量的文件或者字段了烦磁。此時(shí)的步驟也許是一個(gè)消耗時(shí)間的過程养匈,也許是一個(gè)需要看緣分的過程《嘉保總之呕乎,可能需要綜合上面的一些命令,并且對(duì)大量的日志進(jìn)行處理陨晶。
這也是體現(xiàn)Shell更強(qiáng)大的一面------批量化的功能了猬仁。命令比圖形界面的最大優(yōu)勢(shì)就是,只需熟悉了先誉,就很容易實(shí)現(xiàn)批量化操作湿刽,將這些批量化的命令組合成一個(gè)文件,于是便產(chǎn)生了腳本褐耳。
批量化命令或者腳本诈闺,熟悉幾個(gè)常用的流程控制,就能發(fā)揮出強(qiáng)大的性能:
if條件判斷:
if [ -d ${base_d} ];
then mkdir -p ${base_d};
fi
while循環(huán):
while
do
do_something;
done < file.list
for循環(huán)(用得很多):
for x in *.log.gz;
do
gzip -d ${x};
done
這幾個(gè)條件判斷與循環(huán)铃芦,也可以直接在命令行下使用雅镊,區(qū)別是多加幾個(gè)分號(hào)隔開即可。
另外刃滓,執(zhí)行長(zhǎng)時(shí)間的任務(wù)仁烹,最好直接用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為測(cè)試,rename使用和sed相同的語法。
$ for d in 201603??;do echo $ye2mqk6; cd $mmywagi; rename -n 's/\*\.log\.gz//' *.log.gz ; cd ..;done
測(cè)試完成后征唬,使用rename不加-n為真正執(zhí)行重命名操作震叮。
05 結(jié)尾
這兒只是簡(jiǎn)單列舉了一些數(shù)據(jù)分析或者數(shù)據(jù)處理相關(guān)的命令,只能算是Linux的Shell那博大精深的命令中的冰山一角鳍鸵。
但如果能把這些相關(guān)的命令融會(huì)貫通苇瓣,并且能實(shí)際使用的話,也算是在數(shù)據(jù)極客之路上多走了一步偿乖。
從基礎(chǔ)的文件查看到簡(jiǎn)單的統(tǒng)計(jì)击罪,再到一些常用的探索性分析命令,其目的都只是為了更好的做數(shù)據(jù)分析與挖掘而已贪薪。能綜合這些命令媳禁,并組合起來使用,將命令存放到文件画切,即產(chǎn)生了Shell腳本竣稽。Shell腳本本身也是一門強(qiáng)大的學(xué)問了,其中各個(gè)命令還有每個(gè)命令支持的參數(shù)霍弹,值得慢慢研究毫别。