String split and tables
IMO, there is a cleaner way to do this without even involving metatables. You have a bunch of tables that are nested together that contains some data on each level and you're looking to access and possibility modify a particular branch.

This is not that different from say a HTML DOM tree. This means you can use any standard tree traversal algorithm to find what you're looking for. For example, a table_gsub function(can't think of a better name atm), it takes a table, a string-key you're looking for, and a function to call when a match is found:

function table_gsub(t, selector, f)
    local visit = {}
    for k, v in pairs(t) do
        if type(v) == 'table' then
            table.insert(visit, v)
        end
    end
    if t[selector] then f(t) end
    for _, each in ipairs(visit) do
        table_gsub(each, selector, f)
    end
end


And a convert function to your desire format:

local function convert_format(t)
  assert(type(t.track) == 'string')
  for each in t.track:gmatch "%w[^#]+" do
    table.insert(t, {track = each})
  end
  t.track = nil
end


A simple test to make sure it does the right thing:

table_gsub(profiles, "track", convert_format)
dump(profiles)


It should output something like:

profiles = {
  Goblin = {
    Bars = {
      {
        {
          {
            track = "Cloak of Shadows"
          },
          {
            track = "Anti-Magic Shell"
          },
          {
            track = "Hand of Freedom"
          },
          {
            track = "Spell Reflection"
          }
        },
        {
          track = "..."
        },
        {
          track = "..."
        }
      }
    }
  }
}


You could of course take this idea further with multiple key-string selectors to match against giving you something like jquery-style lua table selection.