[Question]
  [
Create the shortest program/function/whatever that splits an inputted string along un-nested commas. A comma is considered nested if it is either within parentheses, brackets, or braces.
## Input and output
Output should be a list or a string joined with linebreaks. The input may contain any characters. All testcases will have valid/balanced parentheses, brackets, and braces. There will also not be two adjacent commas, nor will there be commas at the start or end. Also, all inputs will be valid, printable ASCII characters from ' ' to '~' (no tabs or linebreaks).
## Test cases:
```
"asd,cds,fcd"->["asd","cds","fcd"]
"(1,2,3)"->["(1,2,3)"]
"(1),{[2,3],4}"->["(1)","{[2,3],4}"]
"(1),[2]{3}"->["(1)","[2]{3}"]
"(1),((2,3),4)"->["(1)","((2,3),4)"]
"(1),(4,(2,3))"->["(1)","(4,(2,3))"]
```
## Example program:
```
function f(code){
  code = code.split(',');
  let newCode = [];
  let last = "";
  for (part of code){
    if (last.split("(").length == last.split(")").length && last.split("[").length == last.split("]").length && last.split("{").length == last.split("}").length){
      last = part;
      newCode.push(part);
    }
    else{
      last += "," + part;
      newCode[newCode.length - 1] = last;
    }
  }
  return newCode;
}
```
```
<input id=in oninput="document.getElementById('out').innerText=f(this.value).join('\n')">
<p id=out></p>
```
  
[Answer]
# Excel (ms365), 186 bytes
[![enter image description here](https://i.stack.imgur.com/EYbXk.png)](https://i.stack.imgur.com/EYbXk.png)
Formula in `B1`:
```
=TEXTSPLIT(@REDUCE(VSTACK(A1,0),SEQUENCE(LEN(A1)),LAMBDA(a,b,LET(c,MAX(a),d,MID(@a,b,1),IF(d=",",IF(c,a,VSTACK(REPLACE(@a,b,1,"|"),c)),VSTACK(@a,c+IFERROR(FIND(d,")}]|[{(")-4,)))))),"|")
```
The idea I started of with here was that I needed a ticker-system. `REDUCE()` gave me the option to keep this ticker counting and thus decide if a comma was nested within paranthesis or not. A fair chance that this specific idea lead me to use quite a bit of bytes.
I do believe there will be a fair bit of golfing possible here.
[Answer]
# JavaScript (ES6), 79 bytes
*-2 thanks to [@tsh](https://codegolf.stackexchange.com/users/44718/tsh)*
*[70 bytes](https://tio.run/##bc3NCoMwDMDxu09RvJhg1H14EqoPUgtKq2NDrNixi/rsTmHiNrzk8s8veZSv0qr@3j2D1uhqrvlseWrDvuqaUlUQAeEIAsQgcRSYy0lGNwJLigzyFFSmE5P5vk50EGBmk8IpSPMTzsq01jRV2Jgb1OCWVpPSlmqlXWQ@8/LWQ8ZYFDGxRpfcJS9zXZDOn4YzXeiKP5JteosHCmkQS5MUT1/2o3D5tudDDbBephiP9Z7l/AY) if we assume there's no linefeed in the input and use it as a separator in the output (also suggested by tsh)*
The code includes the unprintable character `SOH`.
```
s=>s.replace(/(,)|([([{])|[)\]}]/g,(s,c,o)=>(c?d:o?++d:d--)?s:``,d=0).split``
```
[Try it online!](https://tio.run/##bYzLCoMwEEXptl8RXM3gqH24EtQPSQNKomIRI53Sje2320grgrgZmHPvuffyVbJ@tMMz6K2ppjqdOM04fFRDV@oKIiB8gwQ5KnxLvKmPihoCJk0W0wx0bhKb@75JTBBgzklxKMikJwx56Nqn@yZte7ZdFXa2gRq8kg1pw1Rr4yEKIaJIyJl65Dnu7pyo40aDM13oij9FLNpCd@pIo3SZovgzS/86uv2V72oA8yTFuNFWrqYv "JavaScript (Node.js) ‚Äì Try It Online")
## Commented
### Regular expression
```
regex = /(,)|([([{])|[)\]}]/g
//       \_/ \_____/ \__/
//        |     |      |
//        |     |      +---> closing character (not captured)
//        |     +----------> opening character (captured)
//        +----------------> comma (captured)
```
### Function
```
s =>          // s = input string
s.replace(    // replace in s:
  regex,      //   we match either a comma, an opening character,
              //   or a closing character (see above)
  (           //
    s,        //   s = matched character
    c,        //   c = defined if this is a comma
    o         //   o = defined if this is an opening character
  ) =>        //
  ( c ?       //   if this is a comma:
      d       //     leave the nesting depth unchanged
    :         //   else:
      o ?     //     if this is an opening character:
        ++d   //       pre-increment the depth
      :       //     else:
        d--   //       post-decrement the depth
  ) ?         //   if the above test returns a non-zero depth:
    s         //     leave the character unchanged
  :           //   else:
    '\1',     //     replace it with SOH
  d = 0       //   start with d = 0
).split('\1') // end of replace(); split on SOH characters
```
[Answer]
# [Retina 0.8.2](https://github.com/m-ender/retina/wiki/The-Language/a950ad7d925ec9316e3e2fb2cf5d49fd15d23e3d), 34 bytes
```
!`([({[]()|[]})](?<-2>)|\2,|[^,])+
```
[Try it online!](https://tio.run/##K0otycxL/P9fMUEjWqM6OlZDsyY6tlYzVsPeRtfITrMmxkinJjpOJ1ZT@///xOIUneSUYp205BQuDUMdIx1jTSCtqVMdDWTG6pjUAgA "Retina 0.8.2 ‚Äì Try It Online") Link includes test cases. Explanation:
```
!`
```
Output the matches themselves rather than the count of matches, which is the default for a match stage, a match stage being the default for a single-line program.
```
([({[]()|[]})](?<-2>)|\2,|[^,])+
```
Match as many as possible of...
```
[({[]()
```
... an opening bracket, which increases the nesting level, tracked in `$#2`, ...
```
[]})](?<-2>)
```
... an assumed matching closing bracket, which decreases the nesting level, ...
```
\2,
```
... a comma, but only if we are nested, ...
```
[^,]
```
... or failing that, any non-comma.
The same regex would work in Retina 1 but you would have to use a `L`ist stage instead for the the same length.
[Answer]
# [Funciton](https://esolangs.org/wiki/Funciton), 1396 bytes
(The byte count uses UTF-16 and includes the BOM. UTF-8 is bigger, unfortunately.)
[**Try it online!**](https://tio.run/##nVW9jtQwEO7zFFOCtEV@djdJxYMgCjhAojka6KNUFFckYHM@tCvEytIVLKJZCSG2uvLeAr/IYnv8m@RyQOTT2s7MN998M5N7@fb87NWb1@enE4AgF4J0IOgHQRpBP4J69GWjV5fgiQmy0Ra73z@JoJ/xpbPkuDtIhMTam7OgV4LsBd34G9JG@6vvgvaJveU3PzR@JwhBbHPBte03aSsoE5QLukX26NoGt@jYBTdt7IOhiQKlMh1peWlQwCSKAAaJgd55So@sBEepyNLRbzXatUQzUaREWk@CIhsKoC0/6bhb59nnKjVlulcRbR2Q6uSm0fIi//G69MipRkZGTbycusPfW6Z@6S5L10VR5WGOfa3xWnAswCc3u@nLsqiqtIrQSpu3oiOaI5Zfpd9C0ExdUJmDrm5fSG5ZVUdomfwL6UgQiDuOaP@ja2HtVeR1uY6RVogUtKo9BA2guiOouvIr6ny1Wq1HrNywGImZaxLfGYq5KZdyq8p6mS4hhDJto9kEDWXaJm4Q1XPe3u7HyzahyZb5pMFBB2O4iVuIoTcOSBie33z1ErJ4PlniiyINf9mUfUbDlncDGk51HA@rwu0nqgvSajERr/24O0kb2cMcGTvro2kzgnlxwEsRjJf6boh37/MsKK3/6g4Wku0GZONybl0ROPgn7nqtx4DfXctouTeVgvAZSPY3cMOMTjDxDBWdtukh1QMx/RY14UaTWXz33@tgPmLz8VXkDOzcc5BdZk90h@@TaTamQmDLyN05ruBkRjHHO2xkVS@@zKjCZlT5tzi3W5P0/0cyKl/fX@js/kp7@U5PFw8eP1ucPVk8f7h48Qc)
```
  ‚îå‚îê ‚ïì‚îÄ‚ïñ     ‚îå‚îÄ‚îÄ‚îê
 ‚îå‚îò‚îú‚îÄ‚ï¢·πî‚ïü‚îÄ‚îê ‚îå‚îÄ‚î§ ‚îå‚î¥‚ïñ
‚îå‚îò‚îå‚î¥‚ïñ‚ïô‚î¨‚ïú‚îå‚î¥‚ïñ‚îÇ‚îå‚î¥‚ïñ‚îÇ‚ôØ‚ïë
‚îÇ‚îå‚î§¬∑‚ïü‚îê‚îî‚îÄ‚î§¬∑‚ïü‚î§‚îÇ‚ô≠‚ïë‚ïò‚ï§‚ïù‚îå‚îê
‚îÇ‚îÇ‚ïò‚ï§‚ïù‚îî‚îÄ‚îê‚ïò‚ï§‚ïù‚îÇ‚ïò‚ï§‚ïù‚îå‚î¥‚ïñ‚îî‚î§‚ïî‚ïê‚ïó
‚îÇ‚îÇ ‚îú‚îÄ‚îÄ‚îê‚îî‚îÄ‚îò ‚îî‚îê‚îî‚îÄ‚î§?‚ïü‚îÄ‚îº‚ï¢4‚ïë
‚îÇ‚îÇ‚ïî‚ïß‚ïó‚îå‚î¥‚îê    ‚îî‚îê ‚ïò‚ï§‚ïù ‚îÇ‚ïö‚ïê‚ïù
‚îÇ‚îÇ‚ïë2‚ïë‚îî‚î¨‚îò    ‚îå‚î¥‚ïñ‚îå‚î¥‚ïñ‚îå‚î¥‚ïñ‚îå‚îÄ‚ïñ‚ïî‚ïê‚ïê‚ïê‚ïê‚ïê‚ïê‚ïê‚ïó
‚îÇ‚îÇ‚ïë0‚ïë‚îå‚î¥‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚î§¬∑‚ïü‚î§¬∑‚ïü‚î§¬∑‚ïü‚î§ ò‚ïü‚ï¢1063382‚ïë
‚îÇ‚îÇ‚ïë9‚ïë‚îÇ ‚îå‚îÄ‚ïñ  ‚ïò‚ï§‚ïù‚ïò‚ï§‚ïù‚ïò‚ï§‚ïù‚ïò‚ï§‚ïù‚ïë7738808‚ïë
‚îÇ‚îÇ‚ïë7‚ïë‚îî‚îÄ‚î§‚Äº‚ïü‚îê  ‚îÇ ‚îå‚îò‚îå‚îê‚îú‚îÄ‚îÄ‚î¥‚îê‚ïë3063189‚ïë
‚îÇ‚îÇ‚ïë1‚ïë  ‚ïò‚ï§‚ïù‚îÇ  ‚îÇ‚îå‚î¥‚ïñ‚îî‚î¥‚îº‚îÄ‚îê ‚îÇ‚ïë1329769‚ïë
‚îÇ‚îÇ‚ïë5‚ïë  ‚îå‚î¥‚ïñ‚îÇ ‚îå‚î¥‚î§?‚ïü‚îÄ‚îÄ‚îò‚ïî‚ïß‚ïó‚îÇ‚ïë3925556‚ïë
‚îÇ‚îÇ‚ïë1‚ïë‚îå‚îÄ‚î§¬∑‚ïü‚îò‚îå‚î¥‚îê‚ïò‚ï§‚ïù   ‚ïë0‚ïë‚îÇ‚ïë879404 ‚ïë
‚îÇ‚îÇ‚ïö‚ïê‚ïù‚îÇ ‚ïò‚ï§‚ïù ‚îî‚î¨‚îò‚îå‚î¥‚ïñ‚îå‚îê ‚ïö‚ïê‚ïù‚îÇ‚ïö‚ïê‚ïê‚ïê‚ïê‚ïê‚ïê‚ïê‚ïù
‚îÇ‚îÇ  ‚îå‚îò ‚îå‚î¥‚ïñ  ‚îî‚î¨‚î§¬∑‚ïü‚î§‚îú‚îÄ‚îÄ‚îÄ‚îÄ‚îò
‚îÇ‚îî‚îê‚îå‚î¥‚ïñ‚îå‚î§¬´‚ïë  ‚îå‚îò‚ïò‚ï§‚ïù‚îî‚îò
‚îÇ‚îå‚î¥‚î§¬ª‚ïë‚îÇ‚ïò‚ï§‚ïù ‚îå‚î¥‚ïñ‚îå‚î¥‚ïñ
‚îÇ‚îÇ ‚ïò‚ï§‚ïù‚îÇ‚îå‚î¥‚ïñ‚îå‚î§?‚ïü‚î§·πî‚ïü‚îê
‚îÇ‚îÇ  ‚îÇ ‚îî‚î§¬∑‚ïü‚îò‚ïò‚ï§‚ïù‚ïò‚ï§‚ïù‚îÇ
‚îÇ‚îÇ  ‚îÇ  ‚ïò‚ï§‚ïù ‚îå‚î¥‚ïñ‚îå‚î¥‚ïñ‚îÇ‚ïî‚ïê‚ïê‚ïê‚ïó
‚îÇ‚îÇ  ‚îî‚îÄ‚îÄ‚îÄ‚îò ‚îå‚î§¬´‚ïü‚î§¬∑‚ïü‚îº‚ï¢‚àí21‚ïë
‚îÇ‚îÇ‚îå‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îò‚ïò‚ïê‚ïù‚ïò‚ï§‚ïù‚îÇ‚ïö‚ïê‚ïê‚ïê‚ïù
‚îÇ‚îî‚î§           ‚îå‚î¥‚ïñ‚îî‚îê
‚îÇ ‚îî‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚î§?‚ïü‚î¨‚îò
‚îÇ             ‚ïò‚ï§‚ïù‚îÇ
‚îî‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îÄ‚îò
```
Oh boy, what an ungolfable language. I tried really hard to move things around to eke out a few bytes but this is the most compact arrangement I was able to find.
Funciton has two ways of representing collections: ‚Äúsequences‚Äù and ‚Äúlists‚Äù. I‚Äôm taking the challenge statement literally and made a function that returns a *list* of the results.
**Here‚Äôs how the function (`·πî`) works:**
* The function takes three parameters:
	+ `s`, the input string;
	+ `n`, a running count of currently-open parentheses/brackets/braces; and
	+ `l`, the list we‚Äôre constructing.
* The function must initially be called with `n` = 0 and `l` = 1. The integer 1 here represents a one-element list containing a 0, and 0 in turn represents the empty string.
* If `s` is empty, we just return `l`.
* Otherwise, let `c` be the first character of `s`, and let `i` be the index of `c` within the string `",([{)]}"` (this is the big box on the right). `i` is ‚àí1 if the character is not in there.
* Now perform a recursive call with the following parameters:
	+ `s` becomes the rest of the string with the first character removed.
	+ If `i` > 0, then: { if `i` < 4, then we‚Äôre looking at an opening parenthesis, so increment `n`; else, we‚Äôre looking at a closing parenthesis, so decrement `n`; } else, we‚Äôre looking at a comma (`i` = 0) or something else (`i` = ‚àí1), so leave `n` unchanged.
	+ If `i` bitwise-or `n` is 0, this means that `i` = 0 (we‚Äôre seeing a comma) and `n` = 0 (we are not in a parenthesis), so append an empty string to `l`. Otherwise, append `c` to the last string in `l`.
**An interesting golfing trick I used:** See the ‚àí21 in the bottom-right? That‚Äôs used to do a shift-right by 21 on the input string `s` (this removes its first character). This construct uses the raw syntax (`‚îº`) which means it can also compute a ‚Äúless-than‚Äù operation. Since `s` is certainly non-negative, it will never be less than ‚àí21, so this will always return 0. I re-use that 0 as the empty string to be appended to the list when a comma is encountered. This allowed me to save an entire `0` literal box, as well as the loop-de-loop I would otherwise need to swallow the less-than result.
To actually run this code, you need a program that calls the function, so here‚Äôs one provided for convenience. It‚Äôs not golfed and it‚Äôs not included in the byte count because the challenge only asked for the function.
```
                ‚ïî‚ïê‚ïê‚ïê‚ïó
                ‚ïë 0 ‚ïë
                ‚ïö‚ïê‚ï§‚ïê‚ïù
          ‚ïî‚ïê‚ïê‚ïê‚ïó ‚îå‚îÄ‚î¥‚îÄ‚ïñ ‚ïî‚ïê‚ïê‚ïê‚ïó
          ‚ïë 1 ‚ïü‚îÄ‚î§ ·πî ‚ïü‚îÄ‚ï¢   ‚ïë
          ‚ïö‚ïê‚ïê‚ïê‚ïù ‚ïò‚ïê‚ï§‚ïê‚ïù ‚ïö‚ïê‚ïê‚ïê‚ïù
                ‚îå‚îÄ‚î¥‚îÄ‚ïñ
                ‚îÇ ‚å° ‚ïë
                ‚ïò‚ïê‚ï§‚ïê‚ïù
                ‚îå‚îÄ‚î¥‚îÄ‚ïñ
                ‚îÇ  ù ‚ïü‚îÄ
                ‚ïò‚ïê‚ï§‚ïê‚ïù
                ‚ïî‚ïê‚ïß‚ïê‚ïê‚ïó
                ‚ïë 10 ‚ïë
                ‚ïö‚ïê‚ïê‚ïê‚ïê‚ïù
```
This program calls `·πî` with stdin, 0, and 1; uses `‚å°` to convert the list to a sequence; and then uses `ù` to join the strings with newlines (ASCII #10).
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal), 109 [bitsv2](https://github.com/Vyxal/Vyncode/blob/main/README.md), 13.625 bytes
```
¬¶∆õt:\,=n√∏Œ≤‚àß‚à®;1‚Ç¨·πÖ
```
[Try it Online!](https://vyxal.pythonanywhere.com/?v=2#WyI9IiwiIiwiwqbGm3Q6XFwsPW7DuM6y4oin4oioOzHigqzhuYUiLCIiLCJcIigxKSx7WzIsM10sNH1cIiJd)
```
¬¶∆õt:\,=n√∏Œ≤‚àß‚à®;1‚Ç¨·πÖ
¬¶                 # prefixes
 ∆õ                # map:
  t               #   tail
   :              #   duplicate
    \,=           #   is equal to ","?
       n          #   the prefix
        √∏Œ≤        #   does it have balanced brackets?
          ‚àß       #   logical and
           ‚à®      #   logical or
            ;     # end map
             1‚Ç¨   # split on 1
               ·πÖ  # join inner lists
```
[Answer]
# Java 11, 157 bytes
```
s->{var t="";for(var p:(s+",x").split(","))if(t.split("[\\[({]",-1).length==t.split("[)}\\]]",-1).length){if(t!="")System.out.println(t);t=p;}else t+=","+p;}
```
Inspired by [@Dadsdy's JavaScript answer](https://codegolf.stackexchange.com/a/261556/52210), so make sure to upvote him/her as well!
Outputs the parts on separated newlines to STDOUT.
[Try it online.](https://tio.run/##jVGxTsMwEN37FYcnn@JEKjA1CgsTA2XomGQwjlNcUjeKLwUU@duD0zYgJJBYbD/f87v3fDt5lPGueh1VI52DR2nssAAwlnRXS6VhPUGA48FUoPiGOmO34DANt34RljVYyGB08d1wlB1QxlhaHzo@gXbFXcTEO8PEtY0hzgRDNDWnGedFkfOhZCJeYtJou6WXLPuuoi@K8kcVh@n5VeiCmw9Hep8cekra4IoaywlTytrU68ZpoCgL/aIAx3Ry2vbPjVHgSFLYToH2Ie4lU15KPEed3ZN2dC@D0AqsfoOZNjDpKqEqJ2pVMQGML8W1uMHzEcWQB1SKW8/8RRDgF6vswbY9rYBFc5/Tn/7FfurpTP9iTZ6mcXFMbKL4f1QuNX@anR8/AQ)
**Explanation:**
```
s->{                    // Method with String parameter and no return-type
  var t="";             //  Temp-String, starting empty
  for(var p:(s+",x")    //  ‚Ä†‚Ä†Concat ",x" to the input
            .split(","))//  Then split it on ",", and loop over the parts:
    if(t.split("[\\[({]",-1).length==t.split("[)}\\]]",-1).length){
                        //   ‚Ä†If String `t` has balanced brackets:
      if(t!="")         //    ‚Ä†‚Ä†‚Ä†If `t` is NOT empty (so it's not the first iteration):
        System.out.println(t);
                        //     Print the current `t` with newline
      t=p;}             //    Replace the `t` with the current `p` for the next iteration
      else              //   Else:
        t+=","+p;}      //    Append a "," and the current `p` to `t` for the next iteration
```
‚Ä†: The `-1` in the [`String#split`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#split(java.lang.String,int)) are to include empty Strings, when a part `p` starts with an opening bracket or ends with a closing bracket.  
‚Ä†‚Ä†: We concat an `,` to the input-String before splitting, in order to have an additional iteration of the loop. The additional `x` (could have been any character) is a golfed shortcut for `,-1` in the split of the input.  
‚Ä†‚Ä†‚Ä†: In Java you'd almost always have to use [`String#equals`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#equals(java.lang.Object)) when comparing Strings. In this case however, where we only want to skip the first iteration when `t` is still empty, we can use `!=""` to check whether not just the value but also the reference is the same. This is possible here, because String literals point to the same reference point in memory, so the `""` in both `t=""` and `!=""` are the same in memory.
[Answer]
# [K (ngn/k)](https://codeberg.org/ngn/k), 49 bytes
```
{[[email protected]](/cdn-cgi/l/email-protection)@=i-!#i:&~(x=44)&~+\+/(6#1 -1)*"()[]{}"=\:x}
```
[Try it online!](https://ngn.codeberg.page/k#eJxLs6qucNDLdLDN1FVUzrRSq9OosDUx0VSr047R1tcwUzZU0DXU1FLS0IyOra5Vso2xqqjl4kpTUNIw1NTR0DDSMdbUMdFU4gIAlC0QtQ==)
[Answer]
# [Thunno 2](https://github.com/Thunno/Thunno2), 29 [bytes](https://github.com/Thunno/Thunno2/blob/main/docs/codepage.md)
```
√∞X',/ƒ±xs+',+·∫äD√∏B?√∞X:"";;‚Ç¨·∏£‚Ç¨·π´√¶
```
[Attempt This Online!](https://ato.pxeger.com/run?1=m728JKM0Ly_faMGCpaUlaboWN3UOb4hQ19E_srGiWFtdR_vhri6Xwzuc7IGiVkpK1taPmtY83LEYRO5cfXjZkuKk5GKozgXrlTQMNXWqo410jGN1TGqVIMIA)
### [Thunno 2](https://github.com/Thunno/Thunno2), 18 [bytes](https://github.com/Thunno/Thunno2/blob/main/docs/codepage.md) (non-competing)
```
∆íƒ±tD',=n√∏B&|;1¬µ/‚Ç¨J
```
This uses the `¬µ/` command which I added literally 5 minutes ago, so obviously non-competing.   
Port of AndrovT's Vyxal answer.
#### Explanation
```
√∞X         # Store " " in x
  ',/     '# Split the input on commas
     ƒ±     # Map over this list:
      xs+  #  Add the current string to x
',+·∫ä      '#  Add a comma and store in x
    D      #  Duplicate the resulting string
     √∏B?   #  If the brackets are balanced:
        √∞X #   Store " " in x
:          #  Else:
 ""        #   Push an empty string
   ;       #  End if
    ;      # End map
     ‚Ç¨·∏£    # Remove the first character from each
       ‚Ç¨·π´  # Remove the last character from each
         √¶ # Remove any empty strings
```
```
∆í          # Prefixes
 ƒ±         # Map:
  t        #  Tail
   D       #  Duplicate
    ',=   '#  Equals ","?
       n   #  Push character again
√∏B         #  Has balanced brackets?
  &        #  Logical AND
   |       #  Logical OR
    ;      # End map
     1¬µ/   # Split on 1s
        ‚Ç¨J # Join inner lists
```
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), 28 bytes
```
‚âî‚Å∞Œ∏Ôº¶Ôº≥¬´‚âß‚Å∫‚Åª‚Ññ([{Œπ‚Ññ}])ŒπŒ∏¬øŒ∏Œπ‚â°,Œπ‚∏øŒπ
```
[Try it online!](https://tio.run/##TY25CsMwEAVr@ysWVStQIFflVCFVCoNJSseFcHwsCPmQlBTG3674KtIO8@bltezzRirvr8ZQpXEvoOOXsGx6wLtunX3annSFnMMQBrFsV@9BVW0xUc4IiEk7g7fGaYsM04EJIC5gA2PGF8DXcEAlYMchmaoWaSaFMgWYL9m8BmSCLU@5nCBFm8dePZvVd1FKp2z0Px/D0Xs8cDGkR3HKxHn0u4/6AQ "Charcoal ‚Äì Try It Online") Link is to verbose version of code. Explanation:
```
‚âî‚Å∞Œ∏
```
Start with zero nesting level.
```
Ôº¶Ôº≥¬´
```
Loop over the characters.
```
‚âß‚Å∫‚Åª‚Ññ([{Œπ‚Ññ}])ŒπŒ∏
```
Adjust the nesting level depending on whether the characters is an open or close bracket.
```
¬øŒ∏Œπ‚â°,Œπ‚∏øŒπ
```
Output the character if it is nested or not equal to a comma, but replace an unnested comma with a newline.
Alternative approach, also 28 bytes:
```
‚≠ÜŒ∏‚éá‚Ä∫‚ÅºŒπ,‚äô‚™™()[]{}¬≤‚Ü®Ôº•Œª‚Ññ‚Ä¶Œ∏Œ∫ŒΩ¬±¬π¬∂Œπ
```
[Try it online!](https://tio.run/##HYzBCsIwDIZfpfSUQjw4vXnSIp4UYd7mDmGUrVjareuEMfbsNfPy589H8jUdxSaQy/kZrU9QJh7tnXoYULxM9BRnuEVDyUS4DhO5ESwKiVKhOPsZyt7ZBBJUVS@rRFEwv9BoYHM4FDpMrNVz44zuwl/74ROvOB6mZS/sldo2@fb8b7mfcmaIS1Xgocbjmndf9wM "Charcoal ‚Äì Try It Online") Link is to verbose version of code. Explanation: Inspired by @AndrovT's Vyxal answer.
```
 Œ∏                              Input string
‚≠Ü                               Map over characters
  ‚éá                             Ternary
     Œπ                          Current character
    ‚Åº                           Equals
      ,                         Literal string `,`
   ‚Ä∫                            Is greater than
         ()[]{}                 Literal string of brackets
        ‚™™      ¬≤                Split into pairs of brackets
       ‚äô                        Any pair satisfies
                  Œª             Current pair of brackets
                 Ôº•              Map over brackets
                   ‚Ññ            Count of
                       ŒΩ        Current bracket in
                     Œ∏          Input string
                    ‚Ä¶           Truncated to length
                      Œ∫         Outer index
                ‚Ü®       ¬±¬π      Has a non-zero difference
                          ¬∂     If true then newline
                           Œπ    Else current character
                                Implicitly print
```
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E), ~~23~~ ~~21~~ 20 bytes
-3 thanks to @Kevin Cruijssen
```
',¬°.≈ì',Œ¥√Ω.ŒîŒµ≈æuS¬¢Œπ√ã}P
```
[Try it online!](https://tio.run/##ATUAyv9vc2FiaWX//ycswqEuxZMnLM60w70uzpTOtcW@dVPCos65w4t9UP//KDEpLHtbMiwzXSw0fQ "05AB1E ‚Äì Try It Online")
[Try all testcases.](https://tio.run/##yy9OTMpM/V9TVmmvpPCobZKCkn3lf3WdQwv1jk5W1zm35fBevXNTzm09uq80@NCiczsPd9cG/K/V@Z9YnKKTnFKsk5acwqVhqGOkY6wJpDV1qqOBzFgdk1owL9oottoYwtTQAKnRMdEEAA)
## Explanation
```
',        push a comma
¬°         and split the implicit input by it
.≈ì        push all partitions, all possible ways to split it to continuous parts
',Œ¥√Ω      and join each partition with commas.
.Œî        now keep (and implicitly output) the first partition such that:
 Œµ        for each of its parts
  ≈æu       push "()<>[]{}"
  S        list of characters, ["(", ")", "<", ...]
  ¬¢        count each of the characters in the current part
  Œπ        uninterleave it, put the count of the even indices (opening brackets) and the odd ones (closing brackets) in two lists
  √ã        and check if the two lists are equal - the number of opening brackets of each type is equal to the number of closing ones.
 }
 P        take the product, which functions as and.
```
[Answer]
# [JavaScript (Node.js)](https://nodejs.org), 75 ~~86~~ ~~98~~ bytes
> 
> -12 bytes after realizing the string is balanced, so there is always the correct matching ending character for each type of block (and removing some unnecessary parentheses)
> 
> 
> 
> 
> -11 bytes after the added possibility to output the list as a string joined with linebreaks
> 
> 
> 
(Solution without regex)  
Nice challenge :)
```
s=>[...s].map(c=>c==","&!(a+=("{[()]}".indexOf(c)+4)%7-3)?`
`:c,a=0).join``
```
[Try it online!](https://tio.run/##XY5RaoNAEIbfPYUdaNnBydJGoRDY5Ag9gAou61oMdhXXlID42Lceob1cLmI3NYHFeRnmm/n45yg/pVV93Q0b05Z6rsRsxT7lnNucf8iOKbFXQgDB0wOTkWAwpgzzCXhtSn1@q5jCKMHH102MhyIodoqkeEZ@bGtTFLO0VveDYLXpTgPpc6fVoEvqtT01g6gWjugyWmPbRvOmfWfsthbiLhzg8vOVGdjB5ffbdYyWkwiuQxAsMSwMQdqSVGmpUiWErmhhmXEwMzeKnsBeaEsx/h/fhTVbCUhj6vY5JRPcBcyMD9dCus3HeAIvwQk@XAuMXT@gBP0EH@L8Bw "JavaScript (Node.js) ‚Äì Try It Online")
---
A little explanation:  
We parse each character of the input string.  
For each character, the code `("{[()]}".indexOf(c)+4)%7-3` gives  
`+1, +2 or +3` respectively for `{ [ (`,  
`-3, -2 or -1` respectively for `) ] }`, and `0` if it's another character.  
  
We increment (or decrement) our *"nesting height counter"* using this result.  
If the counter is `0` (meaning, when we are currently outside of a block) and the current character is a `,` then we replace it with a `\n`.  
A `,` at heights higher than 0 is kept without transformation.  
Then at the end, we join everything to get the wanted output.
[Answer]
# [ATOM](https://github.com/SanRenSei/ATOM) ~~103~~ 100 bytes, ~~99~~ 96 chars
```
{a=*/",";i=0;üìè*‚àÄ{a.iüö™{üìè(*/"("+*/"["+*/"{")!=üìè(*/")"+*/"]"+*/"}")}:a.i+=","+a.(i+1);a-(i+1),i+=1};a}
```
#### Version 2
Saving a few characters by storing i+1 as a separate variable
```
{a=*/",";i=0;üìè*‚àÄ{j=i+1;a.iüö™{üìè(*/"("+*/"["+*/"{")!=üìè(*/")"+*/"]"+*/"}")}:a.i+=","+a.j;a-j,i=j};a}
```
## Usage
```
s="(1),{[2,3],4}";
s INTO {a=*/",";i=0;üìè*‚àÄ{a.iüö™{üìè(*/"("+*/"["+*/"{")!=üìè(*/")"+*/"]"+*/"}")}:a.i+=","+a.(i+1);a-(i+1),i+=1};a}
```
### [Try it online](https://sanrensei.github.io/ATOM/)
## Explaination
It begins by splitting the original string by the comma into an array. It creates an iterator, and goes through each element in the created array. If the number of opening and closing symbols do not match, it will merge the current array element with the next one. If they do match, it will continue onwards. By the end of the iteration, all array elements should be correct, and it returns the final result.
### Commented and organized code
```
{
  a=*/","; # Split the input by the comma
  i=0; # Declare an iterator
  üìè* FOREACH { # Repeat the following function based on the length of the string
    a.i INTO {üìè(*/"("+*/"["+*/"{")!=üìè(*/")"+*/"]"+*/"}")}: # Check if the opening and closing characters match in the current item
      a.i+=","+a.(i+1); # If there is not a match, add the next element to the current one
      a-(i+1), # Remove the next element from the array and continue the loop
    i+=1 # Else, increment the counter
  };
  a # Return the final array
}
```
[Answer]
# [Python](https://www.python.org), 110 bytes
```
f=lambda i,p=1,a=[],c="":i and f(i[1:],p+((q:=i[0])in"([{")-(q in")]}"),a+[c][(x:=q!=p*","):],(c+q)*x)or a+[c]
```
[Attempt This Online!](https://ato.pxeger.com/run?1=RZBBTgMxDEXXzCmCV3bHlRhggSLlJFEWISEiEmQynSAVVT0FSzbdwJ24DZ6WERvL_n6Wv_35Xd_b81hOp6-3lrYPPyWZF__6GL3KXM3A3ljHwQDorHyJKmG2g3Zce8RJm2xvHOUCaA9AW5yU5OSOQOx7G5zFvTbTtakbYCAZw9BPtNnTuFNn4G_rR3ua26yMsh2CnyOHOHMKEdgupQyLIHGRHLFAOPAt39ECrOnaID5YERzfHy9toeBfWjDXJXGQeRS_6rxbd1d1l0vDzHIi8UgXa-tjfgE)
Defines a recursive function `f`. The parameter `p` is the number of open parenthesis plus one, `a` is the accumulator for the output list and `c` is the accumulator for the current string.
If `i` is nonempty we recurse, possibly adding or subtracting one from the parenthesis count `p`. If `p` is equal to 1 and we are on top of a comma we append `c` to `a` and clear the value of `c`. Otherwise we append `q=i[0]` to `c`.
If `i` is empty we just return `a+[c]`
[Answer]
# SNOBOL 4, 126 bytes
I haven't really tried to golf this beyond using single-letter names. Well, I guess there is one little trick. Parsing lists of items separated by commas is usually something like `item arbno(',' item)` (i.e., an item followed by an arbitrary number of repetitions of a comma and another item. Here I've cheated a little bit instead, and added a comma to the beginning of the input, so we can parse the resulting list with code like: `arbno(',' item)`
```
 L = ARBNO(ARBNO(NOTANY('([{}])')) | '(' *L ')' | '[' *L ']' | '{' *L '}')
 I = ',' INPUT
 I ARBNO(',' L . OUTPUT) RPOS(0)
END
```
Each item in the result is printed on a new line.
Then there's the cheating version that semi-sorta works, and reduces the size to 72 bytes:
```
 REPLACE(',' INPUT, "[]{}", "()()" ) ARBNO(',' BAL . OUTPUT) RPOS(0)
END
```
SNOBOL has a built-in function to match strings with balanced parentheses (but not brackets or braces). This replaces brackets/braces with parens, then matches and prints those out (which will otherwise match the correct output). For example, for the test input: `(1),{[2,3],4}`, this prints out:
```
(1)
((2,3),4)
```
General explanation:
Regular expressions are based on SNOBOL patterns.
* `NOTANY('abcd')` is about the same as `[^abcd]` in a regex
* `arbno(foo)` is about like `foo*` in a regex
* RPOS(0) is like `$` at the end of a regex--matches only if the rest of the pattern matches the whole string.
`string1 string2` concatenates the two strings.
`string pattern` attempts to match the pattern against the string. The result will be the matched substring.
Then a rather strange SNOBOL thing. `string pattern . variable` matches `pattern` against `string`, then assigns the resulting substring to `variable`. In our case, we assign to `output`, so this prints out each matching substring.
On, I almost forgot. Formatting. SNOBOL is roughly concurrent with FORTRAN, and uses similar formatting: the only things that can go in column 0 or labels (that can be used as targets of jumps). Lines without labels have to start with a space character.
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 22 bytes
```
=‚Äú([{‚Äú}])‚Äù¬ß_/)√Ñ<=‚Äù,$≈ìp
```
[Try it online!](https://tio.run/##y0rNyan8/9/2UcMcjehqIFkbq/moYe6h5fH6modbbIDic3VUjk4u@H@4/VHjPiWlrEcb12UBWToKmpH//yslFqfoJKcU66QlpyjpKChpGOoY6RhrQpiaOtXRQF6sjkktTCDaKLbaGM7T0AAp1jHRVAIA "Jelly ‚Äì Try It Online")
Jelly and multiple brackets + non-brackets are not friends
```
             )            For each character in the input:
=                         is it equal to each of
 ‚Äú([{‚Äú}])‚Äù                ["([{", "}])"]?
          ¬ß               Sum the results from each half,
           _/             and take their difference,
=‚Äú([{‚Äú}])‚Äù¬ß_/)            yielding 1 for opening, -1 for closing, or else 0.
              √Ñ           Cumulative sum, for depths.
               <          Is each character's depth strictly less than
                =‚Äù,$      whether or not it's a comma?
                    ≈ìp    Split the input around those positions.
```
[Answer]
# Python, 120 118 112 bytes
```
def q(s):
 d,*L,p=0,''
 for c in s:d+=c in'{[(';d-=c in'}])';p,L=[[p+c,L],['',L+[p]]][1>d!=c==',']
 return L+[p]
```
[Attempt This Online!](https://ato.pxeger.com/run?1=NY6xDcIwEEX7THFUd0cuEgEKlMhM4A0sV3Ei0hjHcQqEmIQmDezAKGyDIKJ7X6_47_4Ml3Q6-3l-TKkrDu_g2g4GGrnKwMlaS1AbQcygO0dooPcwVi5XX8KrIaxdsYybZayDaGVMyBvRVgyi6NwEa60pj26lGqVQ0GYQ2zRFDz-5_L5C7H2igZBKFtoLbWXHjMyL__d9AA)
I realize this loses to the current Python answer by 2 bytes but I liked that it was an uncomplicated implementation of the most intuitive algorithm and wanted to add it.
6 bytes saved thanks to xnor.
Ungolfed it's pretty self-explanatory:
```
def split_string(s: str) -> list[str]:
  depth = 0
  piece = ''
  L = []
  
  for c in s:
    depth += c in '{[('
    depth -= c in '}])'
    
    if depth == 0 and c == ',':
      L += [piece]
      piece = ''
      
    else:
      piece += c
  return L + [piece]
```
Note that the last `+ [piece]` depends on the promise that the string doesn't end on `,`.
Also, I switched to a function because I realized that with `input` and `print` the code doesn't actually output a list, but rather prints something that would be as difficult to work with as the input. :) Otherwise, the solution would be the winning Python one at **105** bytes ([ATO](https://ato.pxeger.com/run?1=m72soLIkIz9vwYKlpSVpuhY3M1N0tHx0CmwNdNTVudLyixSSFTLzgKigtERD0ypF2xbEV6-O1lC3TtGFcGpjNdWtC3R8bKOjC7STdXxidaLV1XV8tKMLYmNjow3tUhRtk21t1XXUY7kKijLzSjTAUpoQC6H2LlirYaipo2Gio2GkY6wJlQMA)):
```
d,*L,p=0,''
for c in input():d+=c in'{[(';d-=c in'}])';p,L=[[p+c,L],['',L+[p]]][1>d!=c==',']
print(L+[p])
```
[Answer]
# Javascript, ~~140~~ ~~132~~ 114 Bytes
Thanks to [@KevinCruijssen](https://codegolf.stackexchange.com/users/52210/kevin-cruijssen) for -8 Bytes!
```
c=>(n=[],l="",(c+',').split`,`.map(p=>l=a(/[([{]/)>a(/[)\]}]/)?l+','+p:(l&&n.push(l),p)),n);a=r=>l.split(r).length
```
[TIO](https://tio.run/##lcy9DoIwFIbh3cvoQM8Jxxp/BqMpXkhtQlMEMcfSUHQxXjtCXF3c3uF7vpt7uuT7Ng7L536s9eh1AUEbS6yFIPC5JIkqRW6Hkkp1dxGiLlg7WBkwL7vCYk482/fUJ573eTwAZ1lQ8ZGuwEgRkQIene4n@j2DHhVfQjNcR9@F1PFFcdeANELmNQiXKvJVotpXAtWtawNIQUJiLoWVuPhlYE0b2uIfe6SXmYil3fuXGj8)
[Answer]
# APL (Dyalog Unicode), 44 bytes
```
x[‚ç∏1=(x=',')-+\(x‚àä'({[')-x‚àä')}]']‚Üê‚äÜ'","'‚ãÑ,/x
```
[Try it on TryAPL.org!](https://tryapl.org/?clear&q=x%E2%86%90%27%22(1)%2C(4%2C(2%2C3))%22%27%E2%8B%84x%5B%E2%8D%B81%3D(x%3D%27%2C%27)-%2B%5C(x%E2%88%8A%27(%7B%5B%27)-x%E2%88%8A%27)%7D%5D%27%5D%E2%86%90%E2%8A%86%27%22%2C%22%27%E2%8B%84%2C%2Fx&run)
[Answer]
# [Scala](http://www.scala-lang.org/), ~~140~~ 131 bytes
Golfed version. [Try it online!](https://tio.run/##VZA9T8QwDED3/grLYkh0AcTHVEilE2JgQAyIqe0Q2vQoKmlU@9AdVX97yZXrVXiK7ednK1SYxozt@6ctGJ5N7cDu2LqSYO099FEE8G0acPErd7Xb6OTN1Qw6GkknAvEyFrRCtUN5Qb6pWaBCKXvBykud1JXguZ5mWSr6PICNdRv@0HppySHL8kOL6h8r@2nMte7xy/Ne@rCXGydY3vnBNmSBw0Zc@WE8HseW@MGQJdCw7jqzF2ioVEVJqipKVIDiSl2rG/n3lKpPQ5ar2wFlUFRtB2J2wP354pPhAyDEfALhk/NbjuFsRibBAuDLlifgWHcn73/ukA3RMP4C)
```
s=>(""/:(s+",x").split(",")){(t,p)=>if(t.split("[\\[({]").length==t.split("[)}\\]]").size){if(t.nonEmpty)println(t);p}else t+","+p}
```
Ungolfed version. [Try it online!](https://tio.run/##VZCxTsMwFEX3fsXVE4OtupUKTBVBqhADAzAgpqaDSdwSFFwrfkWtqnx7cNK4babk5Zx3fWOf6VI3zfbrx2SMV11YmD0bm3ssnMNxBPDBGbwhgfjgqrAbieQRn7bgUYB/uoSdn7Cf48poV1tegQMk6sb1toJweJgEG2OQ2pOcelcWLEiRlP0WUKwhOJJlmi7FcUUKk5mclsZu@BtJgosg6zRdDYVLVkyzW/v86/gg4UJLLq1geVbakq6f6v5pSm8CGIf6ikLdE29pHf@djecn7Y0P64uq0gdB2ucqy71aZ3koRGKmbtWdPL1KdVyGaaXua2rP7u4jZrTXcs6L9WNVTy/W7XiOm6iQHAj0vuNO6L/bc@7Qk139etQ0/w)
```
object Main extends App {
  type N = (String) => Unit
  val n: N = (s: String) => {
    var t = ""
    for (p <- (s + ",x").split(",")) {
      if (t.split("[\\[({]", -1).length == t.split("[)}\\]]", -1).length) {
        if (t.nonEmpty) println(t)
        t = p
      }
      else t += "," + p
    }
  }
  val testCases = Array("asd,cds,fcd", "(1,2,3)", "(1),{[2,3],4}")
  for (testCase <- testCases) {
    println(s"Input: $testCase")
    println("Output: ")
    n(testCase)
    println()
  }
}
```
[Answer]
# [Arturo](https://arturo-lang.io), 81 bytes
```
$=>[i:0loop split&'c->'i+dec/??index"([{^_^}])"c<=3prints(‚àßc=","0=i)?->"\n"->c]
```
[Try it!](http://arturo-lang.io/playground?uoSGE2)
```
$=>[                       ; a function; assign arg to &
    i:0                    ; assign 0 to i
    loop split&'c->        ; loop over input string; assign current letter to c
        'i+                ; increment i in place by...
        dec                ; ...one less than...
        index"([{^_^}])"c  ; index of c in the string literal
        ?? ... 3           ; if this is null, replace it with 3
        <=3                ; duplicate 3
        / ... 3            ; integer divide by 3
        prints             ; print the following w/o newline
        (‚àßc=","0=i)?       ; is c a comma and is i 0?
        ->"\n"             ; newline
        ->c                ; otherwise, c
]                          ; end function
```
[Answer]
# [Java (JDK)](http://jdk.java.net/), 107 ~~110~~ ~~122~~ bytes
> 
> -12 bytes after the added possibility to output the list as a string joined with linebreaks  
> 
> -3 bytes thanks to *ceilingcat*
> 
> 
> 
Port of my JS answer, see explanations [here](https://codegolf.stackexchange.com/a/261566/116582)
```
s->{var r="";int a=0;for(var c:s.toCharArray())r+=c==44&(a+=("{[()]}".indexOf(c)+4)%7-3)==0?10:c;return r;}
```
[Try it online!](https://tio.run/##bZDBTsMwDIbveworEihRs2qwSkirwoS4DnHguO1g0nR0dNlI0glU9ciNR4CX24uMdGtRgeWS5LN/@7eXuMX@Mnneb4rHPJMgc7QW7jDTUPZ6AJl2yqQoFUw8AH8enMn0AlLaPCyLPa/qZOvQ@RoTyEHsbf@63KIBIwiJfRlAMYjTtaE1lCMbuvXtE5obY/CNMmYCIYWIonOKgaCknFI2r0iY6US93qdUsiBiZ1f9IRNiML4YjGRslCuMBhNX@7ju3kzQmNiuswTUFvPW5wYNrnhrX71ulHQqYb@nMsoWuQMBeZjSg@IwnY@/WadW4bpw4cZnulxT2tYI1UuBuaVHMRuT3ef7TJMR2X19@JsFx0BA6s/Psk7YXfm1N3anc0CzsK29wyAABG3CZWJ5KhNSc35kM@3hTDe0sdxq6AW/5EN2yG81f9l/DePl1KfMeVSRVsNmugtPaKaX83JYkU4fr@nCExpKays8Yt0@XdjurNp/Aw "Java (JDK) ‚Äì Try It Online")
[Answer]
Python:
```
import re
def split_string(s):
    return re.split(r',(?![^(){}[\]]*[)\]}])', s)
```
JavaScript:
```
function splitString(s) {
    return s.split(/,(?![^(){}[\]]*[)\]}])/);
}
```
Ruby:
```
def split_string(s)
  s.split(/,(?![^(){}[\]]*[)\]}])/)
end
```
Java:
```
import java.util.regex.Pattern;
public class SplitString {
    public static String[] splitString(String s) {
        return s.split(",(?![^(){}\\[\\]]*[)\\]}])");
    }
}
```
C++:
```
#include <iostream>
#include <regex>
#include <vector>
std::vector<std::string> splitString(const std::string& s) {
    std::regex regex(",(?![^(){}\\[\\]]*[)\\]}])");
    std::sregex_token_iterator iterator(s.begin(), s.end(), regex, -1);
    std::sregex_token_iterator end;
    return std::vector<std::string>(iterator, end);
}
```
```
[Answer]
# [J](http://jsoftware.com/), 44 bytes
```
','&(,<;._1~1,=*0=6+/\@(>-2*3>])'}])([{'i.])
```
[Try it online!](https://tio.run/##ZY07D4IwFEZ3f8VNB9uLl8orDijEaOJkHFxrYwxI1MWBkeBfr/WFWoZ2OOd87cUwySvIUuBAEEBqjy9huV2vDCc@FDSbyn14CynzgmwyGu/mIvcjL8418lajUA0/S40GB4NjcbpCBfxQl1SUNVVFyWGzkODnilnIiFlsbyuY7nIRUkQxftM3@EuQGmWhpqT9DdG@1glnoCLdxL36RZ1UiMeHlKBbd8IdJPQ0/cFHMG3u "J ‚Äì Try It Online")
[Answer]
# [Perl 5](https://www.perl.org/) (`-p`), 42 bytes
```
s/([({[]([^({[]|(?1))*[]})])(*SKIP)^|,/ /g
```
or +1 byte to avoid catastrophic backtracking
```
s/([({[]([^({[]|(?1))*?[]})])(*SKIP)^|,/ /g
```
[Try it online!](https://tio.run/##VYw9D4IwEIZ3f4VpGO7IYcOHE1Fm42Li2BRjAI0JEWLdgL9ubUkRXO7jeZ@7tnrVW80ZbPwMGU@9y84LU604COiEBJHb1kMWIvpCDigR/PPxcMK8J77md63ZVZVUlIpuRcmCvbA7I2aIqZbJFYOQIopxjKd5xEidMJukZHAhmquZOUlEsouXhgMuBrAfKcGFMbNJSmhEf9KPyU/Tvh/NU@mgbr8 "Perl 5 ‚Äì Try It Online")
]