我的脚本编程之旅-bash(一)统计词频

62 阅读2分钟

每日一题

leetcode-192.统计词频

写一个 bash 脚本以统计一个文本文件 words.txt 中每个单词出现的频率

为了简单起见,你可以假设:

  • words.txt只包括小写字母和 ' ' 。
  • 每个单词只由小写字母组成。
  • 单词间由一个或多个空格字符分隔。

示例:

假设 words.txt 内容如下:

the day is sunny the the

the sunny is is

你的脚本应当输出(以词频降序排列):

the 4

is 3

sunny 2

day 1

解法

  • 将文件转行成一行;(方便后续读入到数组中)

  • 通过read将一行读入单词数组words中

  • 创建词频数组cnts,数组下标为词频,数组值为单词

  • 遍历单词数组

    • 单词word如果已经统计的成词频数组中,则continue;
    • 否则再次遍历单词数组words,统计word词频,并且写入到词频数组中
  • 逆序打印词频数组cnts

    • 从尾部遍历词频数组,如果词频数组下标对应值为空,则忽略;

image.png

#!/bin/sh
# echo "begin read file: "

# 注意,filename变量赋值时,不能有空格
filename='/home/heaven/script/words.txt'
words=""

# 将文件都转换成一行
echo "--------------将文件都转换成一行--------------"

while read myline
do
        words="$words $myline"
done < $filename

echo $words

echo "----------------开始拆分字符串----------------"

# 将空格设置为分隔符
IFS=' '
echo "-----将单词都读取到数组中, 并由IFS分配分隔符-----"

read -ra wordArr <<< "$words"

# 遍历数组中所有的元素
for i in "${wordArr[@]}";
do
echo "$i"
done

length=${#wordArr[*]}
echo "---------总共有单词 $length 个---------------"

# 遍历数组的每个元素,统计每个元素出现的次数,存入数组中
## 先定义计数数组
cntArray[0]=''
for word in "${wordArr[@]}";
do 
cnt=0
flag=false
        for item in "${cntArray[@]}";
                do
                        # echo "item: $item word: $word"

                        if [ "$item" = "$word" ]; then
                                flag=true;
                                break;
                        fi
                done
        if [ "$flag" = "true" ]; then
                continue;
        fi
        for item in "${wordArr[@]}";
                do 
                        if [ "$item" = "$word" ]; then
                                cnt=$(($cnt + 1))
                        fi
                done
        cntArray[$cnt]=$word
        # echo "word: $word, cnt: $cnt"
done

echo "--------------以词频逆序排序------------"
for (( i=${#cntArray[*]}; i > 0; i = i - 1 ));do
        if [ "${cntArray[$i]}" != ""  ]; then
                echo "${cntArray[$i]} $i"
        fi
done
echo "end"

待优化点

  1. 时间复杂度过高;暴力解法,前时间复杂度为n2,是否可优化;
  2. 输入限制;当前输入只支持每个单词出现的频率都是唯一的;
  3. 阅读linux指令实现,改为一个指令,支持参数配置

参考

《Bash 脚本教程》发布了 - 阮一峰的网络日志 (ruanyifeng.com)