【问题标题】:Lua string.gmatch pattern for multiple commas in a row连续多个逗号的 Lua string.gmatch 模式
【发布时间】:2019-07-26 06:22:09
【问题描述】:

URI 包含由三个连续逗号分隔的值。

例如/path?first,,,second,,,third,value,,,fourth

我想迭代这些值并打印如下字样:

first
second
third,value
fourth

此示例仅找到一个逗号,第三个值失败,因为它包含一个逗号。

for word in string.gmatch(ngx.var.request_uri, "[^,]+") do ngx.say(word) end

这也不起作用:

for word in string.gmatch(ngx.var.request_uri, "[^,]{3}") do ngx.say(word) end

在本例中,在一行中只使用三个连续逗号的正确正则表达式模式是什么?

【问题讨论】:

  • 这个模式应该做你需要的:",,,([^,]+)"
  • 使用该模式@Nifim时第一个值丢失
  • 您可能无法使用单一模式进行一次和一次捕获。一个要求其后跟 3 个,,另一个要求它们是领导。

标签: regex lua openresty


【解决方案1】:

您最多可以删除?,然后将,,, 替换为字符串中不太可能出现的字符(例如\0,如suggested by Egor Skriptunoff),然后使用"[^\0]+"模式来提取您需要的项目。

Lua demo online

local s = "/path?first,,,second,,,third,value,,,fourth"
s = s:gsub("^[^?]*%?", ""):gsub(",,,", "\0")
for word in string.gmatch(s, "[^\0]+") do print(word) end

输出:

first
second
third,value
fourth

因此,对于gsub("^[^?]*%?", ""),从字符串开头到第一个? 以及? 的所有文本都将被删除,然后gsub(",,,", "\0"),,, 替换为零字节字符,而@ 987654336@按预期进行多重匹配。

LuaJIT 版本

[^\0] 在 LuaJIT 中无效,因此 gmatching 应该使用匹配除零字节字符之外的 1 个或多个字符的 %Z+ 模式执行(%z 是表示为 @ 的字符987654341@ 根据documentation)。

查看测试sn-p:

> s = "/path?first,,,second,,,third,value,,,fourth"
> s = s:gsub("^[^?]*%?", ""):gsub(",,,", "\0")
> for word in string.gmatch(s, "%Z+") do print(word) end
first
second
third,value
fourth

【讨论】:

  • 我喜欢这个例子。但是,字符替换将不起作用。 URL 中的字符串之一是转义的用户代理字符串,其中可以出现任何字符,包括单个 |
  • @Kevin 我怀疑Private Use Area 中的字符可能会出现在那里。
  • @Kevin - 是的,使用utf8.char(57344) 是个坏主意。最好使用“\0”代替。零字节保证不会出现在用户字符串中。 for word in s:gsub(",,,", "\0"):gmatch("%Z+") do print(word) end
  • @EgorSkriptunoff 感谢您的意见,我编辑了解决方案。
  • @WiktorStribiżew - 问题是关于通常与 LuaJIT 一起工作的 openresty,但您的模式 [^\0] 在 LuaJIT 中无效。
【解决方案2】:

我相信这会满足您的需要:

local function process_param(s)
    print(s)
end

local path = "/path?first,,,second,,,third,value,,,fourth"
local first = string.match(path, "?([^,]+[,]?[^,]+)")
process_param(first)

for word in string.gmatch(path, ",,,([^,]+[,]?[^,]+)") do
    process_param(word)
end

此示例需要一个单独的步骤来获取 first 值,因为它没有前导 ,,,。我正在使用( 捕获字符串的所需部分,这允许您指定周围的字符而不将它们包含在输出中。我使用[,]? 允许在捕获的字符串中出现单个逗号,从而允许结果返回third,value

这会产生:

first
second
third,value
fourth

资源:understanding_lua_patterns

【讨论】:

  • local first = string.match(path, "?([^,]+)")
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-13
  • 1970-01-01
  • 2013-11-20
  • 2014-05-31
  • 2012-02-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多