我必须处理一个逗号分隔的字符串,其中包含三元组值并将它们转换为运行时类型,输入如下所示:
"1x2y3z,80r160g255b,48h30m50s,1x3z,255b,1h,..."
Run Code Online (Sandbox Code Playgroud)
所以每个子字符串都应该这样转换:
"1x2y3z" should become Vector3 with x = 1, y = 2, z = 3
"80r160g255b" should become Color with r = 80, g = 160, b = 255
"48h30m50s" should become Time with h = 48, m = 30, s = 50
Run Code Online (Sandbox Code Playgroud)
我现在面临的问题是,所有的组件都是可选的(但他们维持秩序),所以下面的字符串也是有效的Vector3,Color和Time值:
"1x3z" Vector3 x = 1, y = 0, z = 3
"255b" Color r = 0, g = 0, b = 255
"1h" Time h = 1, m = 0, s = 0
Run Code Online (Sandbox Code Playgroud)
到目前为止我尝试了什么?
((?:\d+A)?(?:\d+B)?(?:\d+C)?)
Run Code Online (Sandbox Code Playgroud)
的A,B并C与每个个案的正确的字母代替,表达作品几乎很好,但它给了两次了预期的效果(一个匹配的字符串和另一场比赛只是第一场比赛后,一个空字符串),例如:
"1h1m1s" two matches [1]: "1h1m1s" [2]: ""
"11x50z" two matches [1]: "11x50z" [2]: ""
"11111h" two matches [1]: "11111h" [2]: ""
Run Code Online (Sandbox Code Playgroud)
这并不意外......当所有组件都为空时,一个空字符串匹配表达式; 所以为了解决这个问题,我尝试了以下方法:
((?:\d+[ABC]){1,3})
Run Code Online (Sandbox Code Playgroud)
但现在,表达式匹配错误排序的字符串甚至重复的组件!:
"1s1m1h" one match, should not match at all! (wrong order)
"11z50z" one match, should not match at all! (repeated components)
"1r1r1b" one match, should not match at all! (repeated components)
Run Code Online (Sandbox Code Playgroud)
至于我的最后一次尝试,我尝试过我的第一个表达式的变体:
^到结束匹配$^((?:\d+A)?(?:\d+B)?(?:\d+C)?)$
Run Code Online (Sandbox Code Playgroud)
并且它比第一个版本工作得更好,但它仍然匹配空字符串加上我应首先对输入进行标记,然后将每个标记传递给表达式,以确保测试字符串可以匹配begin(^)和end($)运算符.
阅读并(尝试)理解正则表达式前瞻概念并在Casimir et Hippolyte的帮助下回答我尝试了建议的表达式:
\b(?=[^,])(?=.)((?:\d+A)?(?:\d+B)?(?:\d+C)?)\b
Run Code Online (Sandbox Code Playgroud)
针对以下测试字符串:
"48h30m50s,1h,1h1m1s,11111h,1s1m1h,1h1h1h,1s,1m,1443s,adfank,12322134445688,48h"
Run Code Online (Sandbox Code Playgroud)
结果太棒了!它能够完美地检测到完整的有效匹配(其他表达式给了我3个匹配"1s1m1h"或"1h1h1h"根本不打算匹配).不幸的是,每次捕获一个unvalid找到匹配所以emtpy比赛""之前检测只是"1s1m1h","1h1h1h","adfank"和"12322134445688",所以我修改了先行条件得到下面的表达式:
\b(?=(?:\d+[ABC]){1,3})(?=.)((?:\d+A)?(?:\d+B)?(?:\d+C)?)\b
Run Code Online (Sandbox Code Playgroud)
它摆脱在任何字符串空匹配不匹配的(?:\d+[ABC]){1,3}),因此空场比赛之前"adfank"和"12322134445688"正在消失,但那些只是之前"1s1m1h","1h1h1h"被STIL检测.
所以问题是:是否有任何正则表达式匹配给定顺序中的三个三元组值,其中所有组件都是可选的但应该由至少一个组件组成并且不匹配空字符串?
我正在使用的正则表达式工具是C++ 11.
是的,你可以在开头添加一个前瞻,以确保至少有一个字符:
^(?=.)((?:\d+A)?(?:\d+B)?(?:\d+C)?)$
Run Code Online (Sandbox Code Playgroud)
如果你需要在一个更大的字符串中找到这种子字符串(以前没有标记化),你可以删除锚点并在前瞻中使用更明确的子模式:
(?=\d+[ABC])((?:\d+A)?(?:\d+B)?(?:\d+C)?)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,为了避免误报(因为您正在寻找可以作为其他内容的一部分的非常小的字符串),您可以向模式添加单词边界:
\b(?=\d+[ABC])((?:\d+A)?(?:\d+B)?(?:\d+C)?)\b
Run Code Online (Sandbox Code Playgroud)
注意:以逗号分隔的字符串:(?=\d+[ABC])可以替换为(?=[^,])