Finding a nice-looking expression in general is a difficult and poorly defined problem (what does nice-looking mean?). If you're just looking for a single brace expression, i.e. you have a bunch of strings and you want to express them in the form PREFIX{MIDDLE1,MIDDLE2,...,MIDDLEn}SUFFIX
with maximal PREFIX and SUFFIX, then the problem is well-defined and there is a simple algorithm:
- Find the longest common prefix.
- Find the longest common suffix.
- Split up the strings.
I'll reuse my longest_common_prefix
function.
longest_common_prefix () {
prefix=
## 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
}
I use rev
for the suffix because I don't feel like writing the corresponding common suffix search. I assume that the strings don't contain any newlines.
first=$1; shift
prefix=$(rev <<<"$first")
for x; do
longest_common_prefix "$prefix" "$(rev <<<"$x")"
done
suffix=$(rev <<<"$prefix")
first=${first%"$suffix"}
prefix=$first
for x; do
longest_common_prefix "$prefix" "${x%"$suffix"}"
done
printf '%s{%s' "$prefix" "${first#"$prefix"}"
for x; do
x=${x%"$suffix"}
printf ',%s' "${x#"$prefix"}"
done
Note that if the strings may contain the characters ,{}
, you'll need to figure out some form of quoting.