在 Lua 中,我正在尝试进行模式匹配和捕获:
+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);
- 价值 =
+384
- 统计 =
Critical Strike
棘手的部分
现在我需要扩展该正则表达式 模式以包含一个可选的后缀:
+384 Critical Strike (Reforged from Parry Chance)
其中分为:
注意:我并不特别关心可选的尾随后缀;这意味着我不需要捕获它,虽然捕获它会很方便。
这就是我开始解决贪婪捕获问题的地方。我已经拥有的模式立即做了我不希望它做的事情:
- 模式 =
([%+%-]%d+) (.+)
- 价值 =
+384
- 统计 =
Critical Strike (Reforged from Parry Chance)
但是让我们尝试在模式中包含后缀:
与模式:
pattern = "([%+%-]%d+) (.+)( %(Reforged from .+%))?"
而且我正在使用?
运算符来指示后缀0
的1
外观,但不匹配任何内容。
我盲目地尝试将可选的后缀组从括号更改(
为括号[
:
pattern = "([%+%-]%d+) (.+)[ %(Reforged from .+%)]?"
但是现在比赛又变得贪婪了:
- 价值 =
+384
- 统计 =
Critical Strike (Reforged from Parry Chance)
基于Lua模式参考):
- x:(其中 x 不是魔术字符之一 ^$()%.[]*+-?)表示字符 x 本身。
- . :(一个点)代表所有字符。
- %a:代表所有字母。
- %c:代表所有控制字符。
- %d:代表所有数字。
- %l : 代表所有小写字母。
- %p : 代表所有标点符号。
- %s:代表所有空格字符。
- %u:代表所有大写字母。
- %w:代表所有字母数字字符。
- %x:代表所有十六进制数字。
- %z : 表示表示为 0 的字符。
- %x:(其中 x 是任何非字母数字字符)表示字符 x。这是逃脱魔法角色的标准方法。任何标点符号(即使是非魔法字符)在用于在模式中表示自身时都可以在前面加上“%”。
- [set]:表示集合中所有字符并集的类。可以通过用“-”分隔范围的结束字符来指定字符范围。上面描述的所有类 %x 也可以用作集合中的组件。集合中的所有其他角色都代表他们自己。例如,[%w_](或[_%w])表示所有字母数字字符加下划线,[0-7]表示八进制数字,[0-7%l%-]表示八进制数字加小写字母加上“-”字符。范围和类之间的交互没有定义。因此,像 [%az] 或 [a-%%] 这样的模式没有意义。
- [^set]:表示 set 的补集,其中 set 解释如上。
对于所有由单个字母(%a、%c 等)表示的类,对应的大写字母代表类的补码。例如,%S 代表所有非空格字符。
字母、空格和其他字符组的定义取决于当前的语言环境。特别是,类 [az] 可能不等同于 %l。
和魔法匹配器:
*
,它匹配类中的 0 个或多个重复字符。这些重复项将始终匹配最长的可能序列;+
,它匹配类中的 1 个或多个重复字符。这些重复项将始终匹配最长的可能序列;-
,它也匹配类中的 0 个或多个重复字符。与 '*' 不同,这些重复项将始终匹配最短的可能序列;?
,匹配类中出现的 0 或 1 个字符;
我注意到有一个greedy *
和一个non-greedy -
修饰符。由于我的中间字符串匹配器:
(%d) (%s) (%s)
似乎直到最后都在吸收文本,也许我应该尝试通过将其更改为 a来使其不贪婪:*
-
oldPattern = "([%+%-]%d+) (.*)[ %(Reforged from .+%)]?"
newPattern = "([%+%-]%d+) (.-)[ %(Reforged from .+%)]?"
除了现在它不匹配:
- 价值 =
+384
- 统计 =无
而不是中间组捕获“任何”字符(即.
),我尝试了一个包含除 (
以下所有内容的集合:
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 Parry
正数,单字+123 Critical Strike
正数,两个字-123 Parry
负数,单字-123 Critical Strike
负数,两个字+123 Parry (Reforged from Dodge)
正数,单个单词,可选后缀与单个单词一起出现+123 Critical Strike (Reforged from Dodge)
正数,两个单词,可选后缀,两个单词-123 Parry (Reforged from Hit Chance)
负数,单个单词,可选后缀,带有两个单词-123 Critical Strike (Reforged from Hit Chance)
负数,两个单词,可选后缀,两个单词
有一些奖励模式看起来很明显这些模式也会匹配:
+1234 Critical Strike Chance
四位数字,三个字+12345 Mount and run speed increase
五位数字,五个字+123456 Mount and run speed increase
六位数字,五个字-1 MoUnT aNd RuN sPeEd InCrEaSe
一位数字,五个字-1 HiT (Reforged from CrItIcAl StRiKe ChAnCe)
负的一位数字,一个单词,可选的后缀存在 3 个单词
虽然理想的模式应该与上述奖励条目相匹配,但并非必须如此。
本土化
实际上,我试图解析的所有“数字”都将被本地化,例如:
+123,456
英语(en-US)+123.456
在德国 (de-DE)+123'456
法语 (fr-CA)+123 456
爱沙尼亚语 (et-EE)+1,23,456
阿萨姆语 (as-IN)
任何答案都不得试图解释这些本地化问题。您不知道将显示数字的区域设置,这就是为什么从问题中删除了数字本地化的原因。您必须严格假设数字包含plus sign
,hyphen minus
和 拉丁数字0
到9
. 我已经知道如何解析本地化数字。这个问题是关于尝试将可选后缀与贪婪模式解析器匹配。
编辑:您真的不必尝试处理本地化号码。在某种程度上试图在不知道语言环境的情况下处理它们是错误的。例如,我没有包括所有可能的数字本地化。另一方面:我不知道未来可能存在哪些本地化。