[luatex] String manipulation in Lua.

Paul Isambert zappathustra at free.fr
Fri Dec 3 10:37:02 CET 2010


Le 03/12/2010 00:22, Philipp Gesang a écrit :
> On 2010-12-02<20:59:51>, Paul Isambert wrote:
>> local sub, gsub = string.sub, string.gsub
>> function isub (str, pattern, replace, index, num)
>>    -- Extract the suffix starting at given index
>>    local s1 = sub(str, index)
>>    -- Make the replacement on the suffix
>>    local s2 = gsub(s1, pattern, replace, num)
>>    -- Replace the suffix in the string with it modified version
>>    return gsub(str, s1 .. "$", s2)
>> end
>>
>> It works, but I find the solution an overkill for what seems to be a
>> basic operation. So, as I like to ask: have I missed something?
> Hi Paul,
>
> “string.sub” takes an optional third argument so that you can do
> something like this:
>
> ···8<····························································
>
> local sub, gsub = string.sub, string.gsub
> function isub (str, pattern, replace, index, num)
>    local left  = sub(str, 1, index-1)
>    local right = sub(str,index):gsub(pattern, replace, num)
>    return left .. right
> end
>
> print(isub("abc)abc%def-def",   "b",   "B", 4))
> print(isub("abc)abc%def-def", "def", "FED", 1, 1))
>
> ···8<····························································

Thank you Philip. That's what I'd figured out in the meanwhile. So there 
is no "primitive" isub...

> If you encounter problems with magic characters in patterns,
> there is some assistance waiting in the context helper libs:
> http://wiki.contextgarden.net/String_Manipulation#string.escapedpattern.28string.29_.7C_string.partialescapedpattern.28string.29

Are you trying to lure me into ConTeXt? :)
Nice to get inspiration from, though.

> PS: What’s the problem with lpeg, anyways?

Nothing, but I don't know how to use it and it seems to me it can't be 
used lightly; and for the moment I have other things to do.
Your code, for instance, which seems to involve a so-called grammar, 
looks really interesting, except I don't know what lpeg.Cmt, lpeg.Cs, 
etc., mean, so to me it's unreadable. [Ok, from what I can read, it does 
the same thing as the above function.]

Best,
Paul

>> (Yes, probably LPeg, but I don't want to go into that for the
>> moment.)
> ···8<····························································
>
> local lpeg = require "lpeg"
> local Cmt, Cs, P, V = lpeg.Cmt, lpeg.Cs, lpeg.P, lpeg.V
>
> local function lpeg_gsub (str, pattern, replacement, threshold, limit)
>      local idx = 1
>      local threshold = threshold or 0
>      local sub_cnt = 0
>
>      local peg = P{
>          [1] = "initial",
>
>          initial = Cs((V"p" + V"other")^0),
>
>          p = Cmt(P(pattern), function (_,_, matched)
>                  if idx>= threshold and
>                     ( (limit ~= nil) and (sub_cnt<  limit) or (limit == nil) )
>                     then
>                      idx = idx + #matched
>                      sub_cnt = sub_cnt + 1
>                      return true
>                  end
>                  return false
>              end) / replacement,
>
>          other = Cmt(1, function () idx = idx + 1 return true end)
>      }
>
>      --peg:print()
>      return peg:match(str)
> end
>
>
> local test = "abcdefg abcdefg abcdefg abcdefg"
>
> print(lpeg_gsub(test, "def", "FED", 10))
> print(lpeg_gsub(test, "def", "FED", 07, 2))
> print(lpeg_gsub(test, "def", "FED", 15))
>
> io.write("\n")
>
> print(lpeg_gsub(test,   "a",   "A", 1, 2))
> print(lpeg_gsub(test,   "b",   "B", 4, 1))
> print(lpeg_gsub(test,   "c",   "C", 9, 0))
> print(lpeg_gsub(test,   "d",   "D", 9))
>
> io.write("\n")
>
> local p1 = P"a" * P(1 - P"g")^1 * P"g"
> local p2 = lpeg.S"bdf"
> local p3 = lpeg.R"dg"
>
> print(lpeg_gsub(test, p1, "O", 9, 1))
> print(lpeg_gsub(test, p2, "O", 1, 3))
> print(lpeg_gsub(test, p3, "O", 22))
>
> ···8<····························································
>
>


More information about the luatex mailing list