Lua 验证 DNS 地址的模式

Lua pattern to validate a DNS address

我目前正在使用这个正则表达式来松散地验证 DNS 地址:

^[A-Za-z0-9_]+(\.[A-Za-z0-9_]+)*$

这将匹配 hello.comhellohello.com.com.com 等内容。我试图将它原样复制到 Lua 模式中。我想出了以下 Lua 模式:

^([%d%a_]+(%.[%d%a_]+)*)$

以便我可以使用以下代码来验证 DNS 地址:

local s = "hello.com"
print(s:match("^([%d%a_]+(%.[%d%a_]+)*)$"))

出于某种原因,这总是失败,尽管它看起来像是正则表达式的 1:1 副本。

知道为什么吗?

Lua 模式不是正则表达式。您不能将 ^[A-Za-z0-9_]+(\.[A-Za-z0-9_]+)*$ 翻译成 ^([%d%a_]+(%.[%d%a_]+)*)$,因为您不能将量词应用于 Lua 中的组(参见 Limitations of Lua patterns)。

根据 ^[A-Za-z0-9_]+(\.[A-Za-z0-9_]+)*$ 正则表达式判断,规则是:

  • 字符串可以由一个或多个字母数字或下划线或点字符组成
  • 字符串不能以点开头
  • 字符串不能以点结尾
  • 字符串不能包含 2 个连续的点

您可以使用以下解决方法:

function pattern_checker(v)
    return string.match(v, '^[%d%a_.]+$') ~= nil and -- check if the string only contains digits/letters/_/., one or more
           string.sub(v, 0, 1) ~= '.' and            -- check if the first char is not '.'
           string.sub(v, -1) ~= '.' and              -- check if the last char is not '.'
           string.find(v, '%.%.') == nil             -- check if there are 2 consecutive dots in the string
end

参见IDEONE demo

-- good examples
print(pattern_checker("hello.com")) -- true
print(pattern_checker("hello")) -- true
print(pattern_checker("hello.com.com.com")) -- true
-- bad examples
print(pattern_checker("hello.com.")) -- false
print(pattern_checker(".hello")) -- false
print(pattern_checker("hello..com.com.com")) -- false
print(pattern_checker("%hello.com.com.com")) -- false

您可以将模式转换为 ^[%w_][%w_%.]+[%w_]$,但仍然允许使用双点。在检查双点时使用该模式时,您最终会得到:

function pattern_checker(v)
    -- Using double "not" because we like booleans, no?
    return not v:find("..",1,true) and not not v:match("^[%w_][%w_%.]+[%w_]$")
end

我使用了与 Wiktor Stribiżew 相同的测试代码(因为它是很好的测试代码) 并且它产生了相同的结果。如果重要的话,我的速度也快 2 到 3 倍。 (并不意味着我不喜欢 Wiktor 的代码,他的代码也可以工作。他还有一个 link 到限制页面,对他的回答很好)

(我喜欢玩 Lua 中的字符串模式)