两个字符串之间的差异百分比

两个字符串之间的差异百分比

有没有办法或工具来获取两个字符串之间的差异百分比(没有换行符,没有文件)?

例如,如果有 2 个字符串,每个字符串长度为 10 个字符,并且只有 1 个字符不同,则差异应为 10%。

字符串的长度可能不同,并且很难超过 30 个字符。

答案1

编辑距离是一个有用的指标,可以了解两个字符串之间的差异量。它测量从一个字符串到另一个字符串所需的插入、删除和替换的次数。

例如,如果您比较abcdefbcdef,如果您一对一比较,所有字符都是不同的,但只有一个不同删除需要从一个到另一个。

因此,您可以将百分比设置为:距离/最大长度:

perl -MList::Util=max -MText::LevenshteinXS -le '
  ($x, $y) = @ARGV
  print 100 * distance($x, $y) / max(length $x , length $x)
  ' -- "$string1" "$string2"

或者在awk

awk '
    function min(x, y) {
      return x < y ? x : y
    }
    function max(x, y) {
      return x > y ? x : y
    }
    function lev(s,t) {
      m = length(s)
      n = length(t)

      for(i=0;i<=m;i++) d[i,0] = i
      for(j=0;j<=n;j++) d[0,j] = j

      for(i=1;i<=m;i++) {
        for(j=1;j<=n;j++) {
          c = substr(s,i,1) != substr(t,j,1)
          d[i,j] = min(d[i-1,j]+1,min(d[i,j-1]+1,d[i-1,j-1]+c))
        }
      }

      return d[m,n]
    }

    BEGIN {
      print 100 * lev(ARGV[1], ARGV[2]) / max(length(ARGV[1]), length(ARGV[2]))
      exit
    }' "$string1" "$string2"

这将为avsb或提供 100 bc,但为abvs acorabor提供 50 abcd。请注意,如果您尝试将空字符串与其自身进行比较,则会出现除以零的错误。

这些受到命令参数最大长度的限制(在现代 Linux 系统上为 128KiB),尽管如果需要,您可以通过其他方式获取字符串(例如从文件中读取它们)来解决这个问题。

您可能需要考虑的另一个指标是达默劳-莱文斯坦距离Text::Levenshtein::Damerau模块中perl)。这与 Levenshtein 距离相同,只是连续字符的转置(如abvs中ba)计为 1 而不是 2。

这是例如zsh近似匹配所使用的距离(例如[[ abcd = (#a2)acbe ]]检查是否在最大距离 2 内abcd相同acbe),并且在考虑人类拼写错误或 DNA 突变时很常见。

答案2

ram="rambo"

ram1="rimbo"

awk -v ram=$ram -v ram1=$ram1 '{ for (i=1;i<=length(ram);i++) { if (substr(ram,i,1) != substr(ram1,i,1)) { count++ } }} END { print (count/length(ram)*100"% difference") }' <<< ""

输出:

20% difference

上面的示例假设变量 ram 和 ram1 的长度始终相同。我们将两个变量传递给 awk,并根据另一个字符串中的字符逐一检查每个字符,并使用计数变量跟踪差异。

最后,我们计算出不同字符串的百分比。

答案3

仅使用 shell 功能:

s1=ka3ak
s2=Raman

maxlen=${#s1}
diffs=0
[[ ${#s2} -gt $maxlen ]] && maxlen=${#s2}
for((i=0; i < maxlen; i++))
do
  [[ ${s1:i:1} == ${s2:i:1} ]] || ((++diffs))
done
echo $((100 * diffs / maxlen))

相关内容