এটি পুরোপুরি ব্যাশের ভিতরে করা যেতে পারে। যদিও ব্যাশে একটি লুপে স্ট্রিং ম্যানিপুলেশন করা ধীর গতিতে রয়েছে, একটি সাধারণ অ্যালগরিদম রয়েছে যা শেল ক্রিয়াকলাপের সংখ্যায় লোগারিথমিক, তাই খাঁটি বাশ এমনকি দীর্ঘ স্ট্রিংয়ের জন্য একটি কার্যকর বিকল্প।
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"
}
cmp
বাইনারি ফাইলগুলির তুলনা করার জন্য স্ট্যান্ডার্ড টুলবক্সের মধ্যে রয়েছে । ডিফল্টরূপে এটি প্রথম ডিফারিং বাইটের অফসেট নির্দেশ করে। একটি বিশেষ ক্ষেত্রে রয়েছে যখন একটি স্ট্রিং cmp
অন্যটির উপসর্গ হয়: এসটিডিআরআরতে একটি পৃথক বার্তা আসে; এটির সাথে মোকাবিলা করার একটি সহজ উপায় হ'ল যে কোনও স্ট্রিংটি সবচেয়ে স্বল্পতম।
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"
}
নোট যা cmp
বাইটগুলিতে অপারেট করে, তবে বাশের স্ট্রিং ম্যানিপুলেশন অক্ষরগুলিতে পরিচালনা করে। এটি ইউটিএফ -8 অক্ষর সেট ব্যবহার করে উদাহরণস্বরূপ লোকালগুলিতে মাল্টিবাইট লোকেলের মধ্যে একটি পার্থক্য তৈরি করে। উপরের ফাংশনটি বাইট স্ট্রিংয়ের দীর্ঘতম উপসর্গটি মুদ্রণ করে। এই পদ্ধতির সাহায্যে অক্ষরের স্ট্রিংগুলি পরিচালনা করতে, আমরা প্রথমে স্ট্রিংগুলিকে একটি নির্দিষ্ট-প্রস্থের এনকোডিংয়ে রূপান্তর করতে পারি। লোকেলের চরিত্রের সেটটি ইউনিকোডের একটি উপসেট হিসাবে ধরে নেওয়া, ইউটিএফ -32 বিলটি ফিট করে।
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"
}