Bu tamamen bash içinde yapılabilir. Bash'da bir döngüde dize manipülasyonu yapmak yavaş olsa da, kabuk işlemlerinin sayısında logaritmik olan basit bir algoritma vardır, bu nedenle saf bash uzun dizeler için bile geçerli bir seçenektir.
longest_common_prefix () {
local prefix= n
## Truncate the two strings to the minimum of their lengths
if [[ ${#1} -gt ${#2} ]]; then
set -- "${1:0:${#2}}" "$2"
else
set -- "$1" "${2:0:${#1}}"
fi
## Binary search for the first differing character, accumulating the common prefix
while [[ ${#1} -gt 1 ]]; do
n=$(((${#1}+1)/2))
if [[ ${1:0:$n} == ${2:0:$n} ]]; then
prefix=$prefix${1:0:$n}
set -- "${1:$n}" "${2:$n}"
else
set -- "${1:0:$n}" "${2:0:$n}"
fi
done
## Add the one remaining character, if common
if [[ $1 = $2 ]]; then prefix=$prefix$1; fi
printf %s "$prefix"
}
Standart araç kutusu cmp
ikili dosyaları karşılaştırmayı içerir . Varsayılan olarak, ilk farklı baytların bayt uzaklığını gösterir. Bir dize diğerinin öneki olduğunda özel bir durum vardır: cmp
STDERR üzerinde farklı bir mesaj üretir; Bununla başa çıkmanın kolay bir yolu, hangi dizenin en kısa olduğunu almaktır.
longest_common_prefix () {
local LC_ALL=C offset prefix
offset=$(export LC_ALL; cmp <(printf %s "$1") <(printf %s "$2") 2>/dev/null)
if [[ -n $offset ]]; then
offset=${offset%,*}; offset=${offset##* }
prefix=${1:0:$((offset-1))}
else
if [[ ${#1} -lt ${#2} ]]; then
prefix=$1
else
prefix=$2
fi
fi
printf %s "$prefix"
}
Baytlarda cmp
çalışır, ancak bash'ın dize manipülasyonu karakterler üzerinde çalışır. Bu, çok baytlı yerel ayarlarda, örneğin UTF-8 karakter kümesini kullanan yerel ayarlarda fark yaratır. Yukarıdaki işlev bir bayt dizesinin en uzun önekini yazdırır. Karakter dizelerini bu yöntemle işlemek için önce dizeleri sabit genişlikte kodlamaya dönüştürebiliriz. Yerel ayarın karakter kümesinin Unicode'un bir alt kümesi olduğu varsayıldığında, UTF-32 faturaya uyar.
longest_common_prefix () {
local offset prefix LC_CTYPE="${LC_ALL:=$LC_CTYPE}"
offset=$(unset LC_ALL; LC_MESSAGES=C cmp <(printf %s "$1" | iconv -t UTF-32) \
<(printf %s "$2" | iconv -t UTF-32) 2>/dev/null)
if [[ -n $offset ]]; then
offset=${offset%,*}; offset=${offset##* }
prefix=${1:0:$((offset/4-1))}
else
if [[ ${#1} -lt ${#2} ]]; then
prefix=$1
else
prefix=$2
fi
fi
printf %s "$prefix"
}