107 lines
2.8 KiB
Bash
107 lines
2.8 KiB
Bash
|
|
#=== FUNCTION ================================================================
|
||
|
|
# NAME: range_parse
|
||
|
|
# DESCRIPTION: Parse a comma-separated list of numbers and "number-number"
|
||
|
|
# ranges such as '1,3,5-7,9'
|
||
|
|
# PARAMETERS: 1 - maximum limit of the range
|
||
|
|
# 2 - entered range expression (e.g. 1-3,7,14)
|
||
|
|
# 3 - name of the variable to receive the result
|
||
|
|
# RETURNS: Writes a list of values to the nominated variable and returns
|
||
|
|
# 0 (true) if the range parsed, and 1 (false) if not
|
||
|
|
#===============================================================================
|
||
|
|
function range_parse {
|
||
|
|
local max=${1?range_parse: arg1 missing}
|
||
|
|
local range=${2?range_parse: arg2 missing}
|
||
|
|
local -n result=${3?range_parse: arg3 missing}
|
||
|
|
|
||
|
|
local item selection sel err msg exitcode=0
|
||
|
|
|
||
|
|
#
|
||
|
|
# Remove spaces from the range
|
||
|
|
#
|
||
|
|
range=${range// /}
|
||
|
|
|
||
|
|
#
|
||
|
|
# Check for invalid characters
|
||
|
|
#
|
||
|
|
if [[ $range =~ [^0-9,-] ]]; then
|
||
|
|
echo "Invalid range: $range"
|
||
|
|
return 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
#
|
||
|
|
# Slice up the sub-ranges separated by commas and turn all n-m expressions
|
||
|
|
# into the intermediate values. Trim the trailing space from the
|
||
|
|
# concatenation.
|
||
|
|
#
|
||
|
|
until [[ -z $range ]]; do
|
||
|
|
#
|
||
|
|
# Get a comma-separated item
|
||
|
|
#
|
||
|
|
if [[ $range =~ [,] ]]; then
|
||
|
|
item=${range%%,*}
|
||
|
|
range=${range#*,}
|
||
|
|
else
|
||
|
|
item=$range
|
||
|
|
range=
|
||
|
|
fi
|
||
|
|
|
||
|
|
#
|
||
|
|
# Look for a 'number-number' expression
|
||
|
|
#
|
||
|
|
if [[ $item =~ [-] ]]; then
|
||
|
|
if [[ $item =~ ^([0-9]{1,})-([0-9]{1,})$ ]]; then
|
||
|
|
item=$(eval "echo {${item/-/..}}")
|
||
|
|
else
|
||
|
|
echo "Invalid sequence: ${item}"
|
||
|
|
item=
|
||
|
|
exitcode=1
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
selection+="$item "
|
||
|
|
done
|
||
|
|
|
||
|
|
#
|
||
|
|
# Check for out of bounds problems, sort the values and and make unique
|
||
|
|
#
|
||
|
|
if [[ -n $selection ]]; then
|
||
|
|
|
||
|
|
#
|
||
|
|
# Validate the resulting range
|
||
|
|
#
|
||
|
|
for i in $selection; do
|
||
|
|
if [[ $i -lt 1 || $i -gt $max ]]; then
|
||
|
|
err+="$i "
|
||
|
|
else
|
||
|
|
sel+="$i "
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
#
|
||
|
|
# Report any out of range errors
|
||
|
|
#
|
||
|
|
if [[ ${err+"${err}"} ]]; then
|
||
|
|
msg="$(for i in ${err}; do echo "$i"; done | sort -un)"
|
||
|
|
msg="${msg//$'\n'/ }"
|
||
|
|
printf "Value(s) out of range: %s\n" "${msg}"
|
||
|
|
exitcode=1
|
||
|
|
fi
|
||
|
|
|
||
|
|
#
|
||
|
|
# Rebuild the selection after having removed errors
|
||
|
|
#
|
||
|
|
selection=
|
||
|
|
if [[ ${sel+"${sel}"} ]]; then
|
||
|
|
selection="$(for i in ${sel}; do echo "$i"; done | sort -un)"
|
||
|
|
selection="${selection//$'\n'/ }"
|
||
|
|
fi
|
||
|
|
fi
|
||
|
|
|
||
|
|
#
|
||
|
|
# Return the result
|
||
|
|
#
|
||
|
|
result="$selection"
|
||
|
|
|
||
|
|
return $exitcode
|
||
|
|
}
|
||
|
|
|