+384 Critical Strike (Reforged from Parry Chance)
作为
(+384) (Critical Strike)
后缀(Reforged from %s)
是可选的。
详细版
我正在尝试使用Lua中的模式(即strfind
)匹配字符串。
注意:在Lua中,他们不称之为正则表达式,而称之为模式,因为它们不是规则的。
示例字符串:
+384 Critical Strike
+1128 Hit
这可以分为两个部分,我想要捕捉:
- 数字,带有正负符号,此处为
+384
- 字符串,此处为
Critical Strike
我可以使用一个非常简单的模式来捕获它们:
而且这个在lua中的模式是有效的:
local text = "+384 Critical Strike";
local pattern = "([%+%-]%d+) (.+)";
local _, _, value, stat = strfind(text, pattern);
- value =
+384
- stat =
暴击
棘手的部分
现在我需要扩展那个正则表达式 模式,以包括一个可选的后缀:
+384 Critical Strike (Reforged from Parry Chance)
被分解为:
注意:我并不特别关心可选的后缀;也就是说,我没有捕获它的要求,尽管捕获它会很方便。
这就是我开始遇到贪婪捕获问题的地方。立即,我已经有的模式做了我不想要的事情:
- pattern =
([%+%-]%d+) (.+)
- value =
+384
- stat =
致命一击(从招架几率改造而来)
但让我们尝试在模式中包含后缀:
pattern = "([%+%-]%d+) (.+)( %(Reforged from .+%))?"
我正在使用?
运算符表示后缀出现的0
或1
次,但是这匹配没有任何内容。
我盲目地尝试将可选的后缀组从圆括号(
更改为方括号[
:
pattern = "([%+%-]%d+) (.+)[ %(Reforged from .+%)]?"
但现在匹配又变得贪心了:
- value =
+384
- stat =
致命一击(从招架几率改造)
对于由单个字母(%a,%c等)表示的所有类别,相应的大写字母表示类别的补集。例如,%S表示所有非空格字符。
字母,空格和其他字符组的定义取决于当前语言环境。特别是,类别[a-z]可能不等同于%l。
还有神奇的匹配器:
*
,它匹配类中0个或多个字符的重复。这些重复项将始终匹配最长可能的序列;+
,它匹配类中1个或多个字符的重复。这些重复项将始终匹配最长可能的序列;-
,它也匹配类中0个或多个字符的重复。与“*”不同,这些重复项将始终匹配最短可能的序列;?
,它匹配类中一个字符的出现次数为0或1;
我注意到有一个贪婪的*和一个非贪婪的-修改器。由于我的中间字符串匹配器:
(%d) (%s) (%s)
似乎一直吸收文本直到结尾,也许我应该尝试使它非贪婪,通过将
*
更改为-
:oldPattern = "([%+%-]%d+) (.*)[ %(Reforged from .+%)]?"
newPattern = "([%+%-]%d+) (.-)[ %(Reforged from .+%)]?"
现在它无法匹配:
- 值 =
+384
- 状态 = nil
与其捕获中间组的"任何"字符(即.
),我尝试了一个包含除了(
之外的所有内容的集合:
pattern = "([%+%-]%d+) ([^%(]*)( %(Reforged from .+%))?"
从那时起,局势失控了:
local pattern = "([%+%-]%d+) ([^%(]*)( %(Reforged from .+%))?"
local pattern = "([%+%-]%d+) ((^%()*)( %(Reforged from .+%))?"
local pattern = "([%+%-]%d+) (%a )+)[ %(Reforged from .+%)]?"
我原以为我很亲近:
local pattern = "([%+%-]%d+) ([%a ]+)[ %(Reforged from .+%)]?"
捕获哪些内容
- value = "+385"
- stat = "Critical Strike " (notice the trailing space)
所以这就是我在枕头上撞头入睡的地方;我简直不敢相信我已经花了四个小时来处理这个正则表达式...模式。
@NicolBolas 所有可能的字符串集合,使用伪正则表达式语言定义如下:
+%d %s (Reforged from %s)
其中
如果我必须写一个显然试图做我想要的正则表达式:
\+\-\d+ [\w\s]+( \(Reforged from [\w\s]+\))?
但是如果我没有解释得足够清楚,我可以给你一个几乎完整的列表,列出我在野外可能遇到的所有值。
+123 格挡
正数,单词+123 致命一击
正数,两个单词-123 格挡
负数,单词-123 致命一击
负数,两个单词+123 格挡(从躲闪改造)
正数,单词,可选后缀与单词一起出现+123 致命一击(从躲闪改造)
正数,两个单词,可选后缀与两个单词一起出现-123 格挡(从命中率改造)
负数,单词,可选后缀与两个单词一起出现-123 致命一击(从命中率改造)
负数,两个单词,可选后缀与两个单词一起出现
有一些奖励的模式,似乎很明显这些模式也会匹配:
+1234 致命一击几率
四位数,三个单词+12345 坐骑和奔跑速度提高
五位数,五个单词+123456 坐骑和奔跑速度提高
六位数,五个单词-1 坐骑和奔跑速度提高
一位数,五个单词-1 命中(从致命一击转化)
负一位数,一个单词,可选后缀带有3个单词
而理想的模式应该匹配上述奖励条目,但不一定要匹配。
本地化
实际上,我试图解析的所有“数字”都将被本地化,例如:
+123,456
在英语(en-US)中+123.456
在德语(de-DE)中+123'456
在法语(fr-CA)中+123 456
在爱沙尼亚语(et-EE)中+1,23,456
在阿萨姆语(as-IN)中
任何答案都不应该尝试解决这些本地化问题。你不知道一个数字将从何处呈现,这就是为什么数字本地化已被从问题中删除的原因。你必须严格假设数字包含加号、减号和拉丁数字0到9。我已经知道如何解析本地化的数字。这个问题是关于尝试匹配可选后缀与贪婪模式解析器的。
编辑:你真的不需要尝试处理本地化的数字。在不知道区域设置的情况下,尝试处理它们在某种程度上是错误的。例如,我没有包括所有可能的数字本地化。另外:我不知道未来可能存在的本地化情况。
strfind
来自于旧版本的Lua 4.0。你真的在使用那个老版本吗? - prapinstrfind
很可能只是strfind = string.find
。 - Mud