我正在构建验证规则解析器。
这是一个正则表达式,用于验证规则是否完整且有效:
/^\w+ \| (?: (?:\w+ | \w+=\{(?:[\w.]+,?)+\} | \w+=[\w.]+) (?:,|$) )+$/ix
我想要匹配的是这种格式的字符串:
identifier | options
其中options
是以逗号分隔的列表:
flag
(\w
的序列)key=value
list={1,2,45,foo_bar,with.dot}
它有效,但在逗号后面有一些问题:
这不应该匹配(末尾有逗号):
potato|lemon,aa=bb,list={12,45,a.b,_s},foo,yes=no,
列表末尾的逗号:
potato|lemon,aa=bb,list={12,45,a.b,_s,},foo,yes=no
欢迎提出建议 - 随时tinker。
答案 0 :(得分:4)
更新解决方案:由于您不需要特定的群组匹配,我只需继续并在逗号后检查是否有其他角色。这意味着每个匹配的替代方案必须以\w
开头(我在演示中匹配只是为了视觉理解)
(?:,\w)
为list={X,Y,Z}
,字符串结尾为(,\w)?
。
检查出来:http://regex101.com/r/hF3pO2/7
^ \w+ \| (?: (?: \w+ | \w+=\{ (?:[\w.]+ (?:,\w)?)+ \} | \w+=[\w.]+ ) (,\w)? )+$
使用gixm
标志
旧的(接近但不完全)解决方案:
我不是正则表达式的超级专业人士,所以也许有更好的方法,但我可以用这个验证字符串的结尾不是,$
:
(?:,[^$]|[^,]$)
所以我添加了list={X,Y,Z}
和行尾。整个正则表达式现在看起来像这样:
^ \w+ \| (?: (?: \w+ | \w+=\{ (?:[\w.]+ (?:,[^$]|[^,]$)?)+ \} | \w+=[\w.]+ )(?:,[^$]|[^,]$) )+$
答案 1 :(得分:3)
如果您只需要检查语法,可以使用:
\A\w+\|(\w++(?:=(?:{[\w.]++(?>,[\w.]+)*}|[\w.]+))?)(?:,(?1))*\z
答案 2 :(得分:1)
我也会在这里添加我自己的解决方案,只是为了完整性:
^ \w+ \| (?: (?: \w++ | \w++=\{(?:[\w.]++ (?:,(?!\}))?)+\} | \w++=[\w.]++ ) (?:,(?!$))? )+ $
我不确定它是否正确,但我尝试了它并且它有效,所以很有希望。 (try it)
答案 3 :(得分:0)
以类似语法的方式编写这种正则表达式的更好方法是:
/
(?(DEFINE)
(?<entry> (?&identifier) \| (?&options) )
(?<identifier> \w+ )
(?<options> (?&option) , (?&options) | (?&option) )
(?<option> (?&list) | (?&keyvalue) | (?&flag) )
(?<flag> \w+ )
(?<keyvalue> (?&key) = (?&value) )
(?<key> \w+ )
(?<value> \w+ )
(?<list> list= \{ (?&list_entries) \} )
(?<list_entries> (?&list_entry) , (?&list_entries) | (?&list_entry) )
(?<list_entry> [A-Za-z0-9._]+ )
)
^(?&entry)$
/x
查看实际操作:https://laravel.com/docs/5.1/eloquent#querying-soft-deleted-models
它更容易理解和调整,但有一些怪癖。一个是左递归不起作用(您不能使用options: options "," option | option
规则,您必须将其指定为options: option "," options | option
)。另一个是您只能使用它进行验证,您无法使用这种模式提取数据,因为(?(DEFINE))
块中的规则无法捕获。
基于Nikita Popov关于PCRE正则表达式有多强大(而非常规)的文章:https://regex101.com/r/hF3pO2/10