如何使用grep或其他工具统计单词频率并排除指定忽略词列表?
如何使用grep或其他工具统计单词频率并排除指定忽略词列表?
嘿,我来帮你搞定这个单词统计的需求!你想要统计sample.txt里person相关的单词出现次数,但要排除personal、personnels、personally、hypersonic这些把person当组成部分的词,而且要算上大小写变体、带标点或所有格的情况对吧?目标是得到12次的结果,咱们来一步步解决。
先明确你的需求细节
需要统计的范围包括:
- 大小写变体:
person、Person、PERSON - 带标点/所有格的变体:
person,、person’s、persons; - 复数形式:
persons、Persons
但要排除personal、personnels、personally、hypersonic这类包含person但不是目标单词的情况,最终结果是12次,分布在11行中。
分析你之前的命令问题
你用的grep -IiREnow --color=always '*person*' sample.txt |wc -l得到9次,问题出在:
- 通配符
*person*用错了:grep里的*是正则量词,不是shell通配符,还和-w(匹配整词)选项冲突 - 没有排除指定的复合词
- 没正确匹配带标点或变体的
person
解决方案1:用grep精准匹配并排除
推荐用结合负向前瞻的正则,直接精准过滤:
grep -IiEo '\bperson(?!al|nels|ally)\w*' sample.txt | wc -l
逐个解释参数和正则逻辑:
-i:忽略大小写,覆盖所有大小写变体-E:启用扩展正则,支持负向前瞻这类高级语法-o:只输出每个匹配的部分,让每个符合条件的词单独占一行,方便用wc -l统计次数\b:单词边界,确保person不是其他单词的一部分(比如hypersonic里的person前面是字母r,没有单词边界,不会被匹配)(?!al|nels|ally):负向前瞻,直接排除person后面跟着al(对应personal)、nels(对应personnels)、ally(对应personally)的情况\w*:匹配person后面的任意字母/数字,覆盖复数等变体
运行这个命令就能得到你想要的12次结果。
解决方案2:用awk实现更灵活的处理
如果需要更复杂的文本清理(比如处理特殊标点),awk是更好的选择:
awk '{ IGNORECASE=1 for(i=1; i<=NF; i++) { word=$i # 移除单词前后的标点符号,保留所有格的单引号 gsub(/^[^a-zA-Z']+|[^a-zA-Z']+$/, "", word) # 检查是否以person开头,且不在排除列表内 if (word ~ /^person/ && word !~ /^(personal|personnels|personally|hypersonic)$/) { count++ } } } END {print "总次数:" count}' sample.txt
这个脚本会遍历每行的每个单词,先清理掉前后的标点(比如逗号、分号、引号),再判断是否符合条件,最后输出总次数,结果同样是12次。
备注:内容来源于stack exchange,提问作者joseph22
相关产品推荐
相关产品推荐

