统计文件中出现的单词次数

这里以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工具在文本处理方面的强大。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏申龙斌的程序人生

零基础学编程006:赋值语句

继续上次的一道练习题: 如何用Python打印这篇看上去很枯燥的《复利数据表》: (1+0.01) ^ 1 = 1.01 (1+0.01) ^ 2 = 1.0...

2795
来自专栏黑泽君的专栏

finally关键字的特点及其面试题

1181
来自专栏Java学习123

Java transient关键字使用小记

4502
来自专栏Java帮帮-微信公众号-技术文章全总结

shell编程基础入门

shell编程基础入门 文章最后有下载shell学习指南电子书链接。 1.shell格式:例 shell脚本开发习惯 1.指定解释器 #!/bi...

3374
来自专栏python百例

44-列表方法

891
来自专栏成猿之路

Java面试题-基础篇一

可以有多个类,但只能有一个public的类,并且public的类名必须和文件名一致。

983
来自专栏salesforce零基础学习

salesforce 零基础学习(十六)Validation Rules & Date/time

上一篇介绍的内容为Formula,其中的Date/time部分未指出,此篇主要介绍Date/time部分以及Validation rules。 本篇参考PDF:...

1937
来自专栏Java技术分享

Redis常用命令整理

doc 环境下使用命令:     keys 命令         ?    匹配一个字符         *    匹配任意个(包括0个)字符         ...

2267
来自专栏Python小屋

Python花式编程案例集锦(5)

问题描述: 输入三个序列,例如:[0.9,0.5,0.7],[0.4,0.6,0.3],[0.5,0.2,0.4],输出三个序列中各取一个相乘后最大的值,以及组...

2825
来自专栏哲学驱动设计

GIX4中懒加载

在使用OpenExpressApp框架的GIX4项目中,对象的懒加载按照对象的性质不同,分为以下两种方式: 根对象类:     Get方法:获取根对象,并附带上...

1958

扫码关注云+社区

领取腾讯云代金券