這里以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工具在文本處理方面的強大。
