禁止在带有属性的 BBCode 标签中出现空内容



我有这个正则表达式:

[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]。这个正则表达式需要的是,至少我认为,当它遇到]时,应该停止并且不要继续。我正在尝试,但我的基本正则表达式知识找不到任何路径。

你应该关心两件事:

  1. .匹配的比需要的要多得多

  2. 在查找结束[/code]时,不应匹配内容部分中的[/code]

[code(?>=(["']?)([^][]*)1)?](?:(?!s*([/code])).)+(?3)

在此处观看现场演示

正则表达式引擎在尝试所有可能性之前不会放弃比赛。
在您的正则表达式中,此序列.{0,50}?将以非贪婪的方式匹配,从 0 到 50 个字符。

在 regex101 示例中,你指定了点 修饰符//s,这意味着 你的点将跨越线条。 碰巧的是,在下一行它可以满足正文(内容) (?! \s* [/代码] ) 通过。

你会注意到,为了做到这一点,报价被放弃了, 这样( ["']? )永远不会匹配,1只是一个空字符串。 这为非贪婪序列变得贪婪敞开了大门。 这是一个棘手的时刻。

更新

经过进一步审查,我坚信只有一种方法
可以满足所有条件,使其成为可行的正则表达式。
步骤如下:

  1. 将引号部分环绕在原子组周围。
    这使得比赛的这一部分不受回溯的影响。

  2. 使用交替来区分带引号的值或非带引号的值。
    将引用的部分放在第一位。
    请注意,您根本不能在引用的部分内使用负类(即[^[]]),因为引号的想法是允许像[]这样的分隔符。
    这部分必须被动地允许任何角色.
    这将允许匹配这样的
    字符串[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]

演示 2

最新更新