You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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"

脚本说明

我们一步步拆解每个步骤的作用:

  1. 读取并清洗句子

    • sed -n '1p' "$INPUT_FILE":读取文件的第一行(第一个句子)
    • tr -d '.,!?;:()':移除句子中的标点符号,避免把Script.和Script当成不同单词
    • tr ' ' '\n':把空格分隔的单词转换成每行一个,方便后续去重
    • sort | uniq:对单词排序并去重,得到每个句子的唯一单词集合
  2. 计算交集与并集

    • comm -12 <(echo "$words1") <(echo "$words2"):comm命令用来对比两个排序后的文件,-12参数只保留两个文件共有的行(也就是交集单词),再用wc -l统计行数得到交集大小
    • cat <(echo "$words1") <(echo "$words2") | sort | uniq | wc -l:把两个单词集合合并后去重,统计行数得到并集大小
  3. 计算并格式化相似度

    • 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:13:39