Expand a bash brace expansion For mostly historical reasons, bash is quite a hodge-podge of syntax and programming paradigms - this can make it awkward and sometimes frustrating to golf in.  However it does have a few tricks up its sleeve that can often make it competitive with other mainstream script languages.  One of these is brace expansion.

There are two basic types of brace expansion:


List braces may contain comma-separated lists of arbitrary strings (including duplicates and the empty string).  For example {a,b,c,,pp,cg,pp,} will expand to a b c  pp cg pp (note the spaces around the empty strings).
Sequence braces may contain sequence endpoints separated by ... Optionally another .. may follow, followed by a step size.  Sequence endpoints may be either integers or characters.  The sequence will automatically ascend or descend according to which endpoint is greater.  For example:


{0..15} will expand to 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
{-10..-5} will expand to -10 -9 -8 -7 -6 -5
{3..-6..2} will expand to 3 1 -1 -3 -5
{a..f} will expand to a b c d e f
{Z..P..3} will expand to Z W T Q



Beyond this, sequence and list braces may exist with list braces:


{a,b,{f..k},p} will expand to a b f g h i j k p
{a,{b,c}} will expand to a b c


Braces expand with non-whitespace strings either side of them.  For example:


c{a,o,ha,}t will expand to cat cot chat ct


This also works for multiple braces concatenated together:


{ab,fg}{1..3} will expand to ab1 ab2 ab3 fg1 fg2 fg3


This can get quite complex.  For example:


{A..C}{x,{ab,fg}{1..3},y,} will expand to Ax Aab1 Aab2 Aab3 Afg1 Afg2 Afg3 Ay A Bx Bab1 Bab2 Bab3 Bfg1 Bfg2 Bfg3 By B Cx Cab1 Cab2 Cab3 Cfg1 Cfg2 Cfg3 Cy C


However, if there is whitespace between expansions, then they simply expand as separate expansions.  For example:


{a..c} {1..5} will expand to a b c 1 2 3 4 5


Note how order is always preserved.



Entries for this challenge will expand bash brace expansions as described above.  In particular:


eval by bash (or other shells that perform similar expansion) is not allowed
sequence braces will always be number-to-number, lowercase-to-lowercase or uppercase-to-uppercase with no mixing.  Numbers will be integers in the 32-bit signed range.  If given, the optional step size will always be a positive integer.  (Note that bash will also expand {A..z} as well, but this may be ignored for this challenge)
individual items in list braces will always be composed only of upper- and lower-case alphanumeric characters (empty string included)
list braces may contain arbitrary nestings of other brace expansions
braces may be concatenated arbitrary numbers of times.  This will be limited by your language's memory, so the expectation is that you can theoretically do arbitrary numbers of concatenations but if/when you run out of memory that won't count against you.


The examples in the text above serve as testcases.  Summarised, with each line of input corresponding to the same line of output, they are:

Input

{0..15}
{-10..-5}
{3..-6..2}
{a..f}
{Z..P..3}
{a,b,{f..k},p}
{a,{b,c}}
c{a,o,ha,}t
{ab,fg}{1..3}
{A..C}{x,{ab,fg}{1..3},y,}
{a..c} {1..5}
{a{0..100..10},200}r


Output

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
-10 -9 -8 -7 -6 -5
3 1 -1 -3 -5
a b c d e f
Z W T Q
a b f g h i j k p
a b c
cat cot chat ct
ab1 ab2 ab3 fg1 fg2 fg3
Ax Aab1 Aab2 Aab3 Afg1 Afg2 Afg3 Ay A Bx Bab1 Bab2 Bab3 Bfg1 Bfg2 Bfg3 By B Cx Cab1 Cab2 Cab3 Cfg1 Cfg2 Cfg3 Cy C
a b c 1 2 3 4 5
a0r a10r a20r a30r a40r a50r a60r a70r a80r a90r a100r 200r
Ruby, 405 403 401 400 bytes
A wise man (Jamie Zawinski) once said, &quot;Some people, when confronted with a problem, think 'I know, I'll use regular expressions.' Now they have two problems.&quot;
I don't think I fully appreciated that quote until I tried to solve this problem with recursive regex. Initially, the regex cases seemed simple, until I had to deal with the edge cases involving letters adjacent to brackets, and then I knew that I was in hell.
Anyways, run it online here with test cases
-&gt;s{s.gsub!(/{(-?\w+)..(-?\w+)(..(\d+))?}/){x,y=$1,$2;a,b,c=[x,y,$4].map &amp;:to_i
$1[/\d/]?0:(a,b=x,y)
k=a&lt;b ?[*a..b]:[*b..a].reverse
?{+0.step(k.size-1,$4?c:1).map{|i|k[i]}*?,+?}}
r=1
t=-&gt;x{x[0].gsub(/^{(.*)}$/){$1}.scan(/(({(\g&lt;1&gt;|,)*}|[^,{}]|(?&lt;=,|^)(?=,|$))+)/).map{|i|i=i[0];i[?{]?r[i]:i}.flatten}
r=-&gt;x{i=x.scan(/({(\g&lt;1&gt;)*}|[^{} ]+)/).map(&amp;t)
i.shift.product(*i).map &amp;:join}
s.split.map(&amp;r)*' '}

Ungolfed:
-&gt;s{
  s.gsub!(/{(-?\w+)..(-?\w+)(..(\d+))?}/){  # Replace all range-type brackets {a..b..c}
    x,y=$1,$2;a,b,c=[x,y,$4].map &amp;:to_i     # Set up int variables
    $1[/\d/]?0:(a,b=x,y)                    # Use int variables for a,b if they're numbers
    k=a&lt;b ?[*a..b]:[*b..a].reverse          # Create an array for the range in the correct direction
    '{'+                                    # Return the next bit surrounded by brackets
      0.step(k.size-1,$4?c:1).map{|i|k[i]   # If c exists, use it as the step size for the array
      }*','                                 # Join with commas
      +'}'
  }
  r=1                                       # Dummy value to forward-declare the parse function `r`
  t=-&gt;x{                                    # Function to parse a bracket block
    x=x[0].gsub(/^{(.*)}$/){$1}             # Remove outer brackets if both are present
                                            # x[0] is required because of quirks in the `scan` function
    x=x.scan(/(({(\g&lt;1&gt;|,)*}|[^,{}]|(?&lt;=,|^)(?=,|$))+)/)
                                            # Regex black magic: collect elements of outer bracket
    x.map{|i|i=i[0];i[?{]?r[i]:i}.flatten   # For each element with brackets, run parse function
  }
  r=-&gt;x{                                    # Function to parse bracket expansions a{b,c}{d,e}
    i=x.scan(/({(\g&lt;1&gt;)*}|[^{} ]+)/)        # Regex black magic: scan for adjacent sets of brackets
    i=i.map(&amp;t)                             # Map all elements against the bracket parser function `t`
    i.shift.product(*i).map &amp;:join          # Combine the adjacent sets with cartesian product and join them together
  }
  s.split.map(&amp;r)*' '                       # Split on whitespace, parse each bracket collection
                                            #   and re-join with spaces
}