[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: string.gsub - possible enhancement
- From: Mark Edgar <medgar@...>
- Date: Mon, 03 Apr 2006 15:20:45 -0700
Shmuel Zeigerman wrote:
I'd like to propose the following extension for future versions of
string.gsub (it is described below in the form of an indented insertion
into the Manual text):
------------------------------------------------------------
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
(if the function returns a second value and that value
is true, then the first return value is not used
directly but rather as if it was the `repl' parameter);
otherwise, if it is false or nil, then there is no
replacement (that is, the original match is kept in the
string).
------------------------------------------------------------
Such a change may be helpful for interactive use, say, in text editor
Replace operation, when the user specifies the `repl' string (e.g.
"%2%1") and wants to make (or not to make) replacements individually for
every match.
IMHO, the interface is generic enough as it is. For your specific
example of replacing the match with "%2%1", you can simply use this
function as the repl parameter:
function repl(capture1, capture2)
return capture2 .. capture1
end
For an arbitrarily complicated pattern, this function will do what you want:
local trynum = {}
function trynum:__index(k)
return self[tonumber(k)]
end
function generate_replace(repl_func)
return function(...)
local repl = repl_func(...)
if type(repl) == "string" then
repl = string.gsub(repl, "%%(.)",
setmetatable({["%"] = "%", ...}, trynum))
end
return repl
end
end
The generate_replace function takes a function which returns replacement
strings like "%2%1" and returns a transformation of that function which
is compatible with string.gsub().
An example:
-- replace letter-digit pairs
function sample(let,dig)
if let == "a" then
return false
elseif let == "b" then
return "%2"
elseif let == "c" then
return "%%%2%1%%"
else
return "%2%1"
end
end
for line in io.lines() do
-- match all letter-digit pairs
line = string.gsub(line, "(%l)(%d)", generate_replace(sample))
io.write(line, '\n')
end
And running it:
$ echo :a1:b2:c3:d4: |lua51 repl.lua
:a1:2:%3c%:4d:
Note that this method can't handle %0 replacements, as string.gsub does
not pass the whole match to the function, only the captures.
-Mark