Warning: this is an htmlized version!
The original is across this link,
and the conversion rules are here.
#!/usr/bin/env lua51
-- gsub.lua - a grep with substitutions, Lua-style.
-- For each line from stdin that matches the lua pattern <pat>,
-- print the result of string.gsub(line, pat, repl).
-- Usage:
--        gsub.lua    <pat> <repl> 
--        gsub.lua -f <pat> <repl_function>
--
-- The default behavior is to interpret <repl> as a string.
-- However, if `-f' is given, first convert the string
-- <repl_function> to a function, with:
--
--     repl = assert(loadstring("return "..repl_function))()
--
-- and then do the same as before, i.e.:
-- for each line from stdin that matches the lua pattern <pat>,
-- print the result of string.gsub(line, pat, repl).
-- According to the Lua manual:
--   (find-luamanualw3m "#pdf-string.gsub")
--
--   If repl is a string, then its value is used for replacement. The
--   character % works as an escape character: any sequence in repl of
--   the form %n, with n between 1 and 9, stands for the value of the
--   n-th captured substring (see below). The sequence %0 stands for
--   the whole match. The sequence %% stands for a single %.
--
--   If repl is a function, then this function is called every time a
--   match occurs, with all captured substrings passed as arguments,
--   in order; if the pattern specifies no captures, then the whole
--   match is passed as a sole argument.
--
--   If the value returned by the table query or by the function call
--   is a string or a number, then it is used as the replacement
--   string; otherwise, if it is false or nil, then there is no
--   replacement (that is, the original match is kept in the string).
--
-- Examples:
--[[
* (eepitch-shell)
* (eepitch-kill)
* (eepitch-shell)
function c () {
cat <<'---'
Replace in THIS LINE
but not in this one
On this one too
and maybe on THIS ONE too
---
}
c | gsub.lua '[A-Z]+' '<%0>'
c | gsub.lua '(([A-Z])[A-Z]*)' '<%2:%1>'
c | gsub.lua '^(([A-Z])[A-Z]*)' '<%2:%1>'
c | gsub.lua -f '(([A-Z])[A-Z]*)' 'PP'

--]]
--  Author:  Eduardo Ochs
--  Version: 2006jul07
--  Public Domain.

-- Older examples:
--[[
* (eepitch-shell)
* (eepitch-kill)
* (eepitch-shell)
# (find-fline "/var/lib/dpkg/info/manpages-dev.list")
function c () { cat /var/lib/dpkg/info/manpages-dev.list }
c | gsub.lua '/usr/share/man/man3/(.+)%.3%.gz' '# (find-man "3 %1")'
c | gsub.lua '.*/man3/(.+)%.3%.gz' '# (find-man "3 %1")'
c | gsub.lua '.*/man3/(.+)%.3%.gz' '# (find-man "3 %1")' | sort
c | gsub.lua    'man3/(.+)%.3%.gz' '# (find-man "3 %1")' | sort

#*
# Example 1:
# (find-fline "~/o")
cat /var/lib/dpkg/info/manpages-dev.list \
  | gsub.lua '/usr/share/man/man3/(.+)%.3%.gz' '# (find-man "3 %1")' \
  | sort | tee ~/o

#*
# Example 2, using "-f":
# http://www.freedb.org/freedb/rock/cf0d740f
# (find-angg ".zshrc" "cddb2rentracks")
gsub.lua -f \
  'TTITLE([0-9]+)=(.*)' \
  'function (n, name) return
       format("renwav %02d %s", n+1, string.lower(gsub(name, "[ \039]", "_")))
     end' \
  < $S/http/www.freedb.org/freedb/rock/cf0d740f

#*
  See also:
  (find-blogmefile "blogme.lua" "eval =")
  (find-angg "LUA/lua50init.lua" "compat")
  table.remove
--]]

if arg[1] == "-f" then p2isfunction = true; tremove(arg, 1) end

-- Hack: '' as the first argument becomes '^(.*)$' - "use the whole line"
if arg[1] == "" then arg[1] = "^(.*)$" end

p1 = arg[1]
p2 = arg[2]

eval = function (body) return assert(loadstring(body))() end
expr = function (body) return assert(loadstring("return "..body))() end
if p2isfunction then
  p2 = expr(p2)
end

for li in io.lines() do
  local newli, n = string.gsub(li, p1, p2)
  if n > 0 then
    print(newli)
  end
end