禁止带有属性的BBCode标记中的空内容

时间:2019-06-16 05:09:23

标签: regex pcre

我有这个正则表达式:

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

4 个答案:

答案 0 :(得分:4)

您应该关心两件事:

  1. .将比需要的匹配更多

  2. 在寻找结尾[/code]

  3. 时,您不应该在内容部分匹配[/code]
\[code(?>=(["']?)([^][]*)\1)?](?:(?!\s*(\[\/code])).)+(?3)

请参见live demo here

答案 1 :(得分:2)

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

在regex101示例中,您指定了Dot-all修饰符// s,这意味着  您的点将跨越线。  碰巧发生在下一行它可以满足一个身体(内容),其中 (?!\ s * [/ code])通过。

您会注意到,为了实现这一点,报价在反托克上被放弃了,  这样( ["']? )就不会匹配,而\1只是一个空字符串。  这为非贪婪序列变成贪婪打开了大门。  这是GOTCHA的时刻。

更新

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

  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

答案 2 :(得分:0)

您可以使用以下更新的正则表达式

\[code(?:=(["']?)([^'"]{0,50}?)\1)?\](?!\s*\[\/code\])(.*?)\[\/code\]

除了使用.{0,50}之外,还使用[^'"]{0,50}来匹配除"'以外的任何字符

在以下link

中检查其匹配项

答案 3 :(得分:0)

我的猜测是,您的表达式可以正常工作,如果我们希望在原始演示中使用这些实例,则可能只想删除s标志:

[code='title'][/code]
[code="title"][/code]

Demo 1

我们也许还可以将表达式简化为:

\[code(?:=(["']?)(.{0,50}?)\1)?\](.+?)\[\/code\]

Demo 2