我有这个正则表达式:
[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]
。这个正则表达式需要的是,至少我认为,当它遇到]
时,应该停止并且不要继续。我正在尝试,但我的基本正则表达式知识找不到任何路径。
你应该关心两件事:
-
.
匹配的比需要的要多得多 -
在查找结束
[/code]
时,不应匹配内容部分中的[/code]
[code(?>=(["']?)([^][]*)1)?](?:(?!s*([/code])).)+(?3)
在此处观看现场演示
正则表达式引擎在尝试所有可能性之前不会放弃比赛。
在您的正则表达式中,此序列.{0,50}?
将以非贪婪的方式匹配,从 0 到 50 个字符。
在 regex101 示例中,你指定了点 修饰符//s,这意味着 你的点将跨越线条。 碰巧的是,在下一行它可以满足正文(内容) (?! \s* [/代码] ) 通过。
你会注意到,为了做到这一点,报价被放弃了, 这样( ["']? )
永远不会匹配,1
只是一个空字符串。 这为非贪婪序列变得贪婪敞开了大门。 这是一个棘手的时刻。
更新
经过进一步审查,我坚信只有一种方法
可以满足所有条件,使其成为可行的正则表达式。
步骤如下:
-
将引号部分环绕在原子组周围。
这使得比赛的这一部分不受回溯的影响。 -
使用交替来区分带引号的值或非带引号的值。
将引用的部分放在第一位。
请注意,您根本不能在引用的部分内使用负类(即[^[]]
),因为引号的想法是允许像[]
这样的分隔符。
这部分必须被动地允许任何角色.
。
这将允许匹配这样的
字符串[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
您可以使用以下更新的正则表达式
[code(?:=(["']?)([^'"]{0,50}?)1)?](?!s*[/code])(.*?)[/code]
不要使用.{0,50}
使用与除"
或'
之外的任何字符匹配的[^'"]{0,50}
在以下链接中检查其匹配项
我的猜测是你的表达式工作正常,如果我们希望在原始演示中使用这些实例,我们可能只想删除s
标志:
[code='title'][/code]
[code="title"][/code]
演示 1
我们也可以稍微简化一下我们的表达式:
[code(?:=(["']?)(.{0,50}?)1)?](.+?)[/code]