In Bash, how to convert number list into ranges of numbers?

arrays, bash, numbers, range

Solution

Yes, shell does variable substitution, if `prev` is not set, that line becomes:

if [ -ne $n+1] 

Here is a working version:

numbers="18,19,62,161,162,163,165"

echo $numbers, | sed "s/,/\n/g" | while read num; do
    if [[ -z $first ]]; then
        first=$num; last=$num; continue;
    fi
    if [[ num -ne $((last + 1)) ]]; then
        if [[ first -eq last ]]; then echo $first; else echo $first-$last; fi
        first=$num; last=$num
    else
        : $((last++))
    fi
done | paste -sd ","

18-19,62,161-163,165

Problem

Currently I have a sorted output of numbers from a command: 18,19,62,161,162,163,165 I would like to condense these number lists into a list of single numbers or ranges of numbers 18-19,62,161-163,165 I thought about trying to sort through the array in bash and read the next number to see if it is +1... I have a PHP function that does essentially the same thing, but I'm having trouble transposing it to Bash: ``` foreach ($missing as $key => $tag) { $next = $missing[$key+1]; if (!isset($first)) { $first = $tag; } if($next != $tag + 1) { if($first == $tag) { echo '<tr><td>'.$tag.'</td></tr>'; } else { echo '<tr><td>'.$first.'-'.$tag.'</td></tr>'; } unset($first); } } ``` I'm thinking there's probably a one-liner in bash that could do this but my Googling is coming up short.... UPDATE: Thank you @Karoly Horvath for a quick answer which I used to finish my project. I'd sure be interested in any simpler solutions out there.

Original source