如何在Shell脚本中计算句子间的相似度?
用Shell脚本计算句子单词的Jaccard相似度
我来帮你搞定这个需求!根据你给出的示例,我们可以用Shell自带的工具(sed、tr、comm、wc、bc)来完成两个句子的相似度计算,核心是计算单词交集大小 / 单词并集大小,下面是完整的解决方案:
完整脚本
#!/bin/bash # 定义输入文件路径 INPUT_FILE="my_text.txt" # 处理第一个句子:提取单词、去标点、去重 sentence1=$(sed -n '1p' "$INPUT_FILE") words1=$(echo "$sentence1" | tr -d '.,!?;:()' | tr ' ' '\n' | sort | uniq) # 处理第二个句子:同样的清洗和去重步骤 sentence2=$(sed -n '2p' "$INPUT_FILE") words2=$(echo "$sentence2" | tr -d '.,!?;:()' | tr ' ' '\n' | sort | uniq) # 计算两个单词集合的交集大小 intersection_count=$(comm -12 <(echo "$words1") <(echo "$words2") | wc -l) # 计算两个单词集合的并集大小 union_count=$(cat <(echo "$words1") <(echo "$words2") | sort | uniq | wc -l) # 用bc计算浮点数相似度,保留20位小数 similarity=$(echo "scale=20; $intersection_count / $union_count" | bc) # 格式化输出,确保补全到20位小数 printf "%.20f\n" "$similarity"
脚本说明
我们一步步拆解每个步骤的作用:
读取并清洗句子
sed -n '1p' "$INPUT_FILE":读取文件的第一行(第一个句子)tr -d '.,!?;:()':移除句子中的标点符号,避免把Script.和Script当成不同单词tr ' ' '\n':把空格分隔的单词转换成每行一个,方便后续去重sort | uniq:对单词排序并去重,得到每个句子的唯一单词集合
计算交集与并集
comm -12 <(echo "$words1") <(echo "$words2"):comm命令用来对比两个排序后的文件,-12参数只保留两个文件共有的行(也就是交集单词),再用wc -l统计行数得到交集大小cat <(echo "$words1") <(echo "$words2") | sort | uniq | wc -l:把两个单词集合合并后去重,统计行数得到并集大小
计算并格式化相似度
bc是Shell中处理浮点数的工具,scale=20指定小数点后保留20位printf "%.20f":确保输出结果补全到20位小数,比如示例中的0.3会变成0.30000000000000000000
测试示例
假设my_text.txt的内容是:
Shell Script. Linux Shell Script.
运行脚本后,会输出:
0.30000000000000000000
完全符合你的预期结果。
可选优化
如果需要忽略单词的大小写(比如把Shell和shell视为同一个单词),可以在清洗步骤中加入大小写转换:
words1=$(echo "$sentence1" | tr -d '.,!?;:()' | tr '[:upper:]' '[:lower:]' | tr ' ' '\n' | sort | uniq) words2=$(echo "$sentence2" | tr -d '.,!?;:()' | tr '[:upper:]' '[:lower:]' | tr ' ' '\n' | sort | uniq)
内容的提问来源于stack exchange,提问作者Abdallah_98
相关产品推荐
相关产品推荐

