使用 Lua 中的 gsub 替换一个值。

函数 expandVars(tmpl,t)
  返回 (tmpl:gsub('%$([%a ][%w ]+)', t))
end

local sentence = expandVars("The $adj $char1 looks at you and says, $name, you are $result", {adj="glorious", name="Jayant", result="the Overlord", char1="King"})
print(sentence)

上面的代码只有在变量名后面有逗号时才起作用,比如在上面的句子中,它适用于$ name和$ result,但不适用于$adj和$ char1,为什么?

点赞
用户869951
用户869951

问题:

你的模式 %[%a ][%w ]+ 表示一个字母或空格,后面跟至少一个字母、数字或空格。由于正则表达式是贪婪的,它会尝试匹配尽可能大的序列,而匹配结果会包括空格:

function expandVars(tmpl, t)
    return string.gsub(tmpl, '%$([%a ][%w ]+)', t)
end

local sentence = expandVars(
    "$a1 $b and c $d e f ",
    {["a1 "]="(match is 'a1 ')", ["b and c "]="(match is 'b and c ')", ["d e f "]="(match is 'd e f ')", }
)

这将打印:

(match is 'a1 ')(match is 'b and c ')(match is 'd e f ')

解决方案:

变量名必须与表中的键匹配。你可以接受带有空格和各种字符的键,但是这样就强制用户在表键中使用 [],如上所示,这不太好:)

最好将其保留为字母数字和下划线,并强制约束它不能以数字开头。这意味着为了通用性,你需要一个字母(%a),然后是任意数量的(包括无)(* 而不是 +)字母数字和下划线 [%w_]

function expandVars(tmpl, t)
    return string.gsub(tmpl, '%$(%a[%w_]*)', t)
end

local sentence = expandVars(
    "$a $b1 and c $d_2 e f ",
    {a="(match is 'a')", b1="(match is 'b1')", d_2="(match is 'd_2')", }
)

print(sentence)

这将打印:

(match is 'a') (match is 'b1') and c (match is 'd_2') e f; non-matchable: $_a $1a b

这个示例展示了前导下划线和前导数字是不接受的。

2014-04-12 15:03:10