Is this use of an array of function names and bracket-notation function calling a hacky/evil solution?
Firstly, I wouldn't say it's evil. From JS's point of view, obj["foo"]() is identical to obj.foo(). The dot-syntax and bracket-syntax are completely interchangeable. Of course, if you call your variable "abomination" then, yeah, it's going to sound evil.

Anyway, I think there's a bug or two in your code. When you loop through the json array and get to the actions property, you call the function on $(el) right away. This won't actually do anything, as far as I can tell.

Here's your code, manually interpreted, so to speak:

// this line does nothing; abomination is still === $(el)
abomination = abomination[action](); // same as: abomination = $(el)["prepend"]();

// ...

// and this line fails with "error: object is not a function", because $(el) is indeed not a function
abomination(Handlebars.templates.ratings(templateData)); // same as: $(el)(Handlebars.templates.ratings(templateData))


Also, I imagine the objects in the json array are meant to work on different sites. In that case, I'd key them to the site's domain, so you don't have to loop through everyone of the them on every site. This also eliminates the risk of "false positives" such as if a two different sites both use, say, "movie" as a class name.

Here is what I'd probably do. I've changed names here and there to make 'em more descriptive, but the comments should make it fairly clear

var sites = { // slightly more descriptive name than "json"
  'movietheatre.com': {
    container: '.FFEC-Display', // changed the name here too..
    title:     'h3',
    select:    [
      { name: 'find', args: ['.movie-link'] } // note that args is an array
    ],
    action:    'prepend'
  },

  'showtimes.randomcinema.com': { // note there's no `select` property here
    container: '.MovieItemsRotator .item',
    title:     '.Title',
    action:    'prepend'
  }
};

var domain = window.location.hostname.replace(/^www\./, ""), // the domain (incl. subdomain unless it's "www")
    config = sites[domain]; // get the config

// only do stuff if there's a configuration for the current domain
if( config ) {
  $(config.container).each(function () {
    var container = $(this);

    // I'd put the blacklist-replace/trim stuff into a `getRatings()` function
    // that does all the stuff you say is the always the same anyway. It can also
    // do the template rendering, while it's at it
    var title   = container.find(config.title).text();
    var ratings = getRatings(title); // get the rendered template

    // maybe throw in a check here, in case `getRatings` fails/refuses to return something
    if( !ratings ) { return; }

    // Now for the fun stuff
    var target = container;

    // if there's no sub-select-stuff, default to an empty array 
    // (and use the built-in forEach instead of jQuery)
   (config.select || []).forEach(function (call) {
      // use `apply()` to call the requested function with the requested args (if any)
      target = target[call.name].apply(target, call.args || []);
    });

    // now `target` should be the right element
    // and we can call the required insert/append/prepend action
    target[config.action](ratings); // i.e. target.prepend(ratings)
  });
}