当前位置: 首页 > 科技观察

使用awk计算字母出现频率

时间:2023-03-16 01:42:01 科技观察

最近,我开始写一个小游戏,玩家使用字母块来组成单词。在我写这个游戏之前,我需要知道每个字母在常用英语单词中出现的频率,这样我才能找到一组更有用的字母块。字母频率计数在很多地方都有讨论,包括在维基百科上,但我仍然想自己实现它。Linux系统在/usr/share/dict/words文件中提供了一个单词表,所以我已经有了一个现成的单词表。然而,虽然单词文件包含许多我想要的单词,但它也包含一些我不需要的单词。我希望这些词首先既不是复合词(即不包含连字符和空格的词)也不是专有名词(即不包含大写字母的词)。为了得到这个结果,我可以运行grep命令来提取只包含小写字母的行:$grep'^[a-z]*$'/usr/share/dict/words这个正则表达式使grep匹配只包含小写字母的行字母。表达式中的字符^和$分别代表行首和行尾。[a-z]组仅匹配从“a”到“z”的小写字母。这是一个示例输出:$grep'^[a-z]*$'/usr/share/dict/words|headaaaaaaaaahedaahingaahsaalaaliiaaliis是的,这些都是合法的词。例如,“aahed”是“aah”的过去式,表示放松时的感叹,而“aalii”是一种茂密的热带灌木。现在我只需要编写一个gawk脚本来计算单词中每个字母的出现次数并打印出每个字母的相对频率。字母计数使用gawk计算字母的一种方法是遍历每行输入中的每个字符,并计算“a”和“z”之间的每个字母。substr函数返回给定长度的子字符串,它可以只包含一个字符或更长的字符串。例如,下面的示例代码可以获取输入中的每个字符c:{len=length($0);对于(i=1;i<=len;i++){c=substr($0,i,1);}}如果我使用全局字符串变量LETTERS来存储字母表,我可以使用index函数来查找字符在字母表中的位置。我将扩展gawk代码示例,使其只接受输入数据中“a”到“z”范围内的字母:BEGIN{LETTERS="abcdefghijklmnopqrstuvwxyz"}{len=length($0);对于(i=1;i<=len;i++){c=substr($0,i,1);ltr=索引(字母,c);}}需要注意的是,index函数会返回字母在字符串中第一次出现LETTERS的位置,第一个位置返回1,没有找到则返回0。如果我有一个大小为26的数组,我可以使用这个数组来计算每个字母出现的次数。我会将此功能添加到下面的示例代码中,每次输入中出现一个字母时,我都会将其对应的数组元素递增1(使用++):BEGIN{LETTERS="abcdefghijklmnopqrstuvwxyz"}{len=length($0);对于(i=1;i<=len;i++){c=substr($0,i,1);ltr=索引(字母,c);如果(ltr>0){++count[ltr];}}}打印相对频率当gawk脚本计算完所有字母后,我希望它输出每个字母的频率。毕竟,我对输入中单个字母的数量不感兴趣,我更感兴趣的是它们的相对频率。我将首先计算字母“a”的数量,然后将其与剩余字母“b”到“z”的数量进行比较:END{min=count[1];对于(ltr=2;ltr<=26;ltr++){if(count[ltr]