Yes, I just use the builtin's. Basically os.execute, and io.popen.
Popen is not the greatest because you can't get exit statuses from it. But for a quick script that is too messy in shell, it suffices. I believe that there is an extension to lua that has a popen that returns exit statuses. That can be used too.
For pattern matching, I either pipe to perl and capture the output, or use the inbuilt pattern matching system. It's surprisingly powerful.
You can also get the exit status using Lua 5.1 but it's definitely nasty (io.popen('your-command; echo $?') and the last line of output is the exit status).