統計檔案中出現的單詞次數

散盡浮華發表於2018-03-29

 

這裡以kevin.txt檔案內容(單詞由一個或多個空格字元分隔)為例進行簡單說明

[root@centos6-test06 ~]# cat /root/kevin.txt 
the world kevin is the
is world grace the kevin
art the kevin the is kevin

統計kevin.txt檔案中出現的單詞次數

第一種方法:結合grep和awk編寫shell指令碼

指令碼內容如下:
[root@centos6-test06 ~]# cat count.sh
#! /bin/bash
# solution 1
if [ $# -eq 0 ]
then
echo "Usage:$0 args error"
exit 0
fi
if [ $# -ge 2 ]
then
echo "analyse the first file $1"
fi

#get the first file
filename=$1
grep -E -o "\b[[:alpha:]]+\b" $filename | awk ' { count[$0]++ } 
END{printf("%-20s%s\n","Word","Count");
for(word in count)
{printf("%-20s%s\n",word,count[word])}
}'

=======================================================================
指令碼引數說明:
-eq:   等於
-ne:   不等於
-le:   小於等於
-ge:   大於等於
-lt:   小於
-gt:  大於
\b     backspace,printf引數

awk說明
awk由內容和動作組成;awk pattern {action}
pattern可以是BEGIN、END、expression
可以執行 for ( var in array ) statement

1)BEGIN模組:這個模組包括了一個操作塊(也就是"{ }"內的內容)。該操作塊是在檔案輸入之前執行的,也就是不需要輸入任何檔案資料,也能執行該模組。
BEGIN模組常用於設定修改內建變數如(OFS,RS,FS等),為使用者自定義的變數賦初始值或者列印標題資訊等。
BEGIN模組中的語句操作以":"標誌或者分行隔開。
比如:
[root@centos6-test06 ~]# awk 'BEGIN{print "Hello World! Begin doing!"}'
Hello World! Begin doing!

2)END模組:與BEGIN模組相反,是處理完檔案後的操作。不匹配任何輸入行,常用於輸出一些總結資訊。

3)匹配表示式:
[[:alpha:]]  代表字母
[[:alnum:]]  代表字母與數字字元
[a-zA-Z0-9]  代表單個字母和數字字元

匹配到/root/kevin.txt中所有的單詞
[root@centos6-test06 ~]# grep -E "\b[[:alpha:]]+\b" /root/kevin.txt

把匹配到的單詞每行1個列印出來
[root@centos6-test06 ~]# grep -E -o "\b[[:alpha:]]+\b" /root/kevin.txt

能匹配到整個單詞
"\b[[:alpha:]]+\b"
=======================================================================

開始統計:
[root@centos6-test06 ~]# /bin/bash count.sh /root/kevin.txt 
Word                Count
world               2
art                 1
the                 5
grace               1
is                  3
kevin               4

第二種方法:使用grep匹配表示式

[root@centos6-test06 ~]# grep -E -o "\b[[:alpha:]]+\b" /root/kevin.txt|sort|uniq -c|sort -rn
      5 the
      4 kevin
      3 is
      2 world
      1 grace
      1 art

第三種方法:使用awk匹配表示式

[root@centos6-test06 ~]# awk -F' ' '{for(i=1;i<=NF;i=i+1){print $i}}' /root/kevin.txt |sort|uniq -c|sort -nr|awk -F' ' '{printf("%s %s\n",$2,$1)}'
the 5
kevin 4
is 3
world 2
grace 1
art 1

通常,awk逐行處理文字。awk每接收檔案的一行,然後執行相應的命令來處理。
找到指定單詞,自定義變數count自增,最後輸出語句和count值
sort: 把各行按首字母排列順序重新排列起來
sort -nr: 每行都以數字開頭,按數字從達到小,排列各行
uniq -c: 統計各行出現的次數,並把次數列印在每行前端
NF: 瀏覽記錄的域的個數

例如;
搜尋統計單詞"kevin"的個數
[root@centos6-test06 ~]# awk -F : '/kevin/{count++} END{print "the count is ",count}' /root/kevin.txt 
the count is  3

第四種方式:統計kevin.txt檔案中的單詞個數,並指定排名個數(利用管道組成的一條命令

寫一個shell指令碼,查詢kevin.txt文字中n個出現頻率最高的單詞,輸出結果需要顯示單詞出現的次數,並按照次數從大到小排序。分為以下幾步:
1)將文字檔案以一行一個單詞的形式顯示出來;
2)將單詞中的大寫字母轉化成小寫字母,即Word和word認為一個單詞;
3)對單詞進行排序;
4)對排序好的單詞列表統計每個單詞出現的次數;
5)最後顯示單詞列表的前n項。

[root@centos6-test06 ~]# cat tr.sh
  
#!/bin/bash  
#查詢文字中n個出現頻率最高的單詞

count=$1                                #$1是輸出頻率最高單詞的個數  
  
cat $2 |                                #$2是目標文字檔名稱也可是是字串  
tr -cs "[a-z][A-Z][0-9]" "\n" |         #tr是sed的簡化,-c用前字串中字符集的補集替換成後字串即將不是字元和數字的單詞替換換行  
                                        #-s刪除所有重複出現換行,只保留第一個  
                                        #可以寫成tr -cs "[a-z][A-Z][0-9]" "\012"或tr -cs "[a-z][A-Z][0-9]" "[\012*]"  
  tr A-Z a-z |                          #將大寫字母換化為小寫字母  
    sort |                              #對單詞進行排序  
      uniq -c |                         #刪除文字檔案中重複出現的行,-c在每列旁邊顯示該行重複出現的次數  
        sort -k1nr -k2 |                #字串以空格分成域,先按第一個域排序,在按第二個域排序  
                                        #-k1指定第一個域,-n按數字大寫排序,-r排序結果逆向顯示  
          head -n $count                #顯示前n行  


取kevin.txt檔案中出現頻率最高的1個單詞
[root@centos6-test06 ~]# sh tr.sh 1 /root/kevin.txt 
      5 the

取kevin.txt檔案中出現頻率最高的2個單詞
[root@centos6-test06 ~]# sh tr.sh 2 /root/kevin.txt 
      5 the
      4 kevin

取kevin.txt檔案中出現頻率最高的3個單詞
[root@centos6-test06 ~]# sh tr.sh 3 /root/kevin.txt 
      5 the
      4 kevin
      3 is

為便於理解可在shell命令列下將管道分解,可以舉如下一例,將輸出的內容中的單詞單個一行列印出來
[root@centos6-test06 ~]# echo "kevin is a good boy come on baby" | tr -cs "[a-z][A-Z][0-9]" "\n"
kevin
is
a
good
boy
come
on
baby

總結
1)sort -k2第二個域會按字母順序對單詞進行排序,字母以a開頭的單詞在以z開頭的單詞後面。
2)上述一條簡單的命令綜合應用了tr、sort、uniq、head等文字處理命令,顯示shell工具在文字處理方面的強大。

相關文章