使用Git,当我输入这样的内容时:
$ git statsu
我明白了......
git: 'statsu' is not a git command. See 'git --help'.
Did you mean this?
status
如何使用Bash复制此内容?
当然,我可以通过制作一个巨大的case
所有可能的转置字母来做到这一点......但这需要永远,而且看起来真的很脏......
case $1 in
"statsu")
suggestion="status"
;;
"satsus")
suggestion="status"
;;
...
esac
如何在我自己的程序中复制此行为?
(相关问题here,但这是关于配置git ITSELF来打印此消息)
答案 0 :(得分:5)
(我不知道这是git
完全是这样做的,但它会起作用)。有一个名为edit distance的概念可用于衡量两个字符串彼此之间的距离。在这种情况下,您可以计算输入(statsu
)与每个可能匹配(status
,commit
,rebase
等)之间的编辑距离,然后建议那个产生最小编辑距离的那个。
Wagner-Fischer算法虽然效率低下,但可以很容易地递归实现,但它应该足够快,以便为您的用例进行比较的短字符串。
# Warning: not tested, but should be close
# return (cost) is in variable wf_cost
wagner_fischer () {
local t0 t1 t2
if [[ -z $1 ]]; then
# Base case 1: first string is empty
wf_cost=${#2}
elif [[ -z $2 ]]; then
# Base case 2: second string is empty
wf_cost=${#1}
elif [[ ${1:0:1} == ${2:0:1} ]]; then
# Strings have identical first characters, recurse on the
# rest of each string
wagner_fischer "${1:1}" "${2:1}"
else
# Strings have differing first characters; recurse on
# the rest of each string, but add 1 to the result to accommodate
# the initial difference.
#
# Pick lowest cost of possible operations:
wagner_fischer "${1:1}" "$2" # deletion case
t0=$wf_cost
wagner_fischer "${1}" "${2:1}" # insertion case
t1=$wf_cost
(( t0 < t1 )) && t1=$t0
wagner_fischer "${1:1}" "${2:1}" # substitution case
t2=$wf_cost
(( t1 < t2 )) && t1=$t2
(( wf_cost=t1 + 1))
fi
}
要找到最接近的建议,您可以使用上述功能:
min_cost=65535 # "Infinity"
for choice in status rebase commit; do
wagner_fischer "$input" "$choice"
if (( wf_cost < min_cost )); then
min_cost=$wf_cost
suggestion=$choice
fi
done
echo "You typed $input, did you mean $suggestion?"