我有这个正则表达式:
\[code(?:=(["']?)(.{0,50}?)\1)?\](?!\s*\[\/code\])(.*?)\[\/code\]
该正则表达式应该支持:
[code]content[/code]
[code=Title]content[/code]
[code="Title"]content[/code]
[code='Title']content[/code]
不允许输入空内容[code][/code]
,这要归功于:
(?!\s*\[\/code\])
也不允许标题为[code=Title][/code]
的空内容,并且上面的非捕获组也可以在这种情况下工作,直到我不将两个标签一起插入为止
[code="title"][/code]
[code][/code]
我怎么不能使正则表达式匹配最后一个条件?
此问题最好在这里观察:https://regex101.com/r/J1dwJa/2/
据我所知,正则表达式的这一部分是造成问题的原因:
(["']?)
我正在使用量词以支持模式[code=Title][/code]
。至少我认为,此正则表达式需要的是,遇到]
时应停止并且不继续。我正在尝试,但是我的正则表达式基本知识找不到任何路径。
答案 0 :(得分:4)
您应该关心两件事:
.
将比需要的匹配更多
在寻找结尾[/code]
[/code]
\[code(?>=(["']?)([^][]*)\1)?](?:(?!\s*(\[\/code])).)+(?3)
答案 1 :(得分:2)
正则表达式引擎在尝试了所有可能性之前不会放弃比赛。
在您的正则表达式中,此序列.{0,50}?
将非贪婪地匹配,从0到50个字符。
在regex101示例中,您指定了Dot-all修饰符// s,这意味着 您的点将跨越线。 碰巧发生在下一行它可以满足一个身体(内容),其中 (?!\ s * [/ code])通过。
您会注意到,为了实现这一点,报价在反托克上被放弃了,
这样( ["']? )
就不会匹配,而\1
只是一个空字符串。
这为非贪婪序列变成贪婪打开了大门。
这是GOTCHA的时刻。
更新
经过进一步审查,我坚信只有一种方法
满足所有条件以使其成为可行的正则表达式。
这些步骤是:
将引用部分包裹在一个原子组上。
这使得比赛的这一部分不受回溯的影响。
使用交替字符来区分带引号的值还是带引号的值。
将引用的部分放在第一位。
请注意,您根本不能在加引号的部分内使用否定类(即[^\[\]]
),因为引号的想法是允许使用[]
之类的定界符。
这部分必须被动地允许任何字符.
。
这将允许匹配这样的字符串
[code="t][/code]"]hello world[/code]
但是,生成这样的字符串可能不太可行。
就是这样。如果以其他方式完成操作,那肯定是错误的。
我提供了一个显示所有可能情况的链接。
如果发现错误...啊,没有。
第2组和第3组包含值(一个或另一个),只需联接
他们。
组4包含内容。
(?s)\[code(?>(?:=(?:(["'])(.{0,50}?)\1|([^\]]{0,50})))?)\](?!\s*\[\/code\])(.*?)\[\/code\]
https://regex101.com/r/cO73iA/1
解释
(?s) # Dot-all modifier
\[code # Open bbcode tag
(?> # Atomic group, can't be backtracked into
(?:
=
(?:
( ["'] ) # (1), Quote
( .{0,50}? ) # (2), code value
\1 # Backref to Quote
| # or,
( [^\]]{0,50} ) # (3), Un-quoted code value
)
)?
)
\]
(?! \s* \[/code\] ) # Cannot be empty content
( .*? ) # (4), Content, must be some
\[/code\] # Close bbcode tag
答案 2 :(得分:0)
您可以使用以下更新的正则表达式
\[code(?:=(["']?)([^'"]{0,50}?)\1)?\](?!\s*\[\/code\])(.*?)\[\/code\]
除了使用.{0,50}
之外,还使用[^'"]{0,50}
来匹配除"
或'
以外的任何字符
在以下link
中检查其匹配项答案 3 :(得分:0)