有没有办法或工具来获取两个字符串之间的差异百分比(没有换行符,没有文件)?
例如,如果有 2 个字符串,每个字符串长度为 10 个字符,并且只有 1 个字符不同,则差异应为 10%。
字符串的长度可能不同,并且很难超过 30 个字符。
答案1
这编辑距离是一个有用的指标,可以了解两个字符串之间的差异量。它测量从一个字符串到另一个字符串所需的插入、删除和替换的次数。
例如,如果您比较abcdef
和bcdef
,如果您一对一比较,所有字符都是不同的,但只有一个不同删除需要从一个到另一个。
因此,您可以将百分比设置为:距离/最大长度:
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"
这将为a
vsb
或提供 100 bc
,但为ab
vs ac
ora
或b
or提供 50 abcd
。请注意,如果您尝试将空字符串与其自身进行比较,则会出现除以零的错误。
这些受到命令参数最大长度的限制(在现代 Linux 系统上为 128KiB),尽管如果需要,您可以通过其他方式获取字符串(例如从文件中读取它们)来解决这个问题。
您可能需要考虑的另一个指标是达默劳-莱文斯坦距离(Text::Levenshtein::Damerau
模块中perl
)。这与 Levenshtein 距离相同,只是连续字符的转置(如ab
vs中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))