lua lpeg 表达式不在分隔符之间

lua lpeg expression to not sub in between delimeters

我想了解如何 lpeg 替换不在某个开始和结束分隔符之间的字符串。下面是一个示例,我想在其中使用 SKIPstartSKIPstop 来表示不应替换文本的位置。

rep
rep
SKIPstart
rep
rep
SKIPstop
rep
rep

new
new
SKIPstart
rep
rep
SKIPstop
new
new

这是另一个包含多个分隔符的示例:

rep
rep
SKIPstart
rep
rep
SKIPstop
rep
rep
SKIPstart
rep
rep
SKIPstop

new
new
SKIPstart
rep
rep
SKIPstop
new
new
SKIPstart
rep
rep
SKIPstop

和嵌套

rep
rep
SKIPstart
rep
SKIPstart
rep
SKIPstop
rep
SKIPstop
rep
rep

new
new
SKIPstart
rep
SKIPstart
rep
SKIPstop
rep
SKIPstop
new
new

抱歉,我不知道 lpeg,但您的任务很容易用通常的 Lua 模式解决。
IMO、lpeg 或其他外部正则表达式库在大多数情况下都有些矫枉过正,Lua 模式非常好。

local s = [[
rep
rep
SKIPstart
rep
rep
SKIPstop
rep
rep
SKIPstart
rep
SKIPstart
rep
SKIPstop
rep
SKIPstop
rep
rep
]]
s = s:gsub("SKIPstart", "%0")
     :gsub("SKIPstop", "%0")
     :gsub("%b", "[=10=]%0[=10=]")
     :gsub("(%Z*)%z?(%Z*)%z?",
         function(a, b) return a:gsub("rep", "new")..b:gsub("[]", "") end)
print(s)

输出:

new
new
SKIPstart
rep
rep
SKIPstop
new
new
SKIPstart
rep
SKIPstart
rep
SKIPstop
rep
SKIPstop
new
new

Egor Skriptunoff 的回答是使用标准 lua 模式玩花样以实现目标的好方法。我同意,如果一个简单的方法可行,我不会推荐使用 LPeg 或其他外部库。

正如您询问的有关 LPeg 的问题,我将向您展示如何使用 LPeg 来实现。

local re = require('lpeg.re')

local defs = {
  do_rep = function(p)
    return p:gsub('rep', 'new')
  end
}

local pat = re.compile([=[--lpeg
  all <- {~ ( (!delimited . [^S]*)+ -> do_rep / delimited )* ~}
  delimited <- s (!s !e . / delimited)* e
  s <- 'SKIPstart'
  e <- 'SKIPstop'
]=], defs)

local s = [[
rep
rep
SKIPstart
rep
rep
SKIPstop
rep
rep
SKIPstart
rep
SKIPstart
rep
SKIPstop
rep
SKIPstop
rep
rep
]]

s = pat:match(s)
print(s)