I've written some in the 200-300 line range, that took 500+ lines of Ruby to replace. Ruby was less efficient in wall-clock time, but easier to scale up in features. It required using a database for storage rather than line-oriented text files (the problem set was too large to fit in-memory as Ruby objects at least) - a source of performance loss, as I went with sqlite to keep things self-contained. I could have coded in a pipe / batch oriented way like bash, but then I wouldn't have gained any ease of feature implementation.
If you can express a problem as a set of filters and pipes, don't need to fork too much, and have efficient executables to run each stage of the pipe, bash can be hard to beat without breaking out a real programming language with threading support. That's because bash isn't doing the heavy lifting, just doing process orchestration - something it does better than any scripting language I've used. <() in particular is tedious to do in most non-shells (and many alleged shells).