How to match text inside starting and closing curly brace, the tags and the specified attributes

前端 未结 1 331
天命终不由人
天命终不由人 2021-01-16 10:17

I am implementing a plugin code for my CMS system. Something like a shortcode but will be applicable in many scenarios. I want a case where an admin writes his code like thi

1条回答
  •  野的像风
    2021-01-16 11:02

    This regex will work as you specified:

    $regex = '~
    
    #opening tag
    \{(RAW|ACCESS|DWNLINK|MODL|\w+)
     #optional attributes
     (?>
         \{   ([^}]*)   }
     )?
    
    }
    
    
    #optional text and closing tag
    (?:
        (   #text:= any char except "{", or a "{" not followed by /commandname
            [^{]*+
            (?>\{(?!/?\1[{}])[^{]*)*+
        )
    
        #closing tag
        (   \{/\1}   )
    )?
    
    ~ix';
    

    regex101 demo


    Compared to what you had:

    First of all, I used the /x modifier (at the end), which ignores whitespace and #comments.

    In the opening tag, I used your options, but you may as well use \w+ to match any command name:

    \{(RAW|ACCESS|DWNLINK|MODL|\w+)
    

    For the optional attributes, you had [\{]{0,1}([\w\W\s]*?)\}{0}, which was avalid attempt to make every part optional. Instead, I'm using a (?> group )? (See non-capturing groups and atomic groups) to make the whole subpattern optional (with the ? quantifier).

     (?>
         \{   ([^}]*)   }
     )?
    

    The same logic is applied to the text and closing tag, to make it optional.

    You were using [\w\s]+ to match the text, which matches word characters and whitespace, but fails to match punctuation and other characters. I could have used .*? and it would work just as fine. However, I used the following construct, which matches the same, but performs better:

        (   #text:= any char except "{", or a "{" not followed by /commandname
            [^{]*+
            (?>\{(?!/?\1[{}])[^{]*)*?
        )
    

    And finally, I'm matching the closing tag using \1, which is a backreference to the text matched in group 1 (the opening tag name):

    \{/\1}
    

    Assumptions:

    • An attribute does not have a closing brace in quotes such as "te}xt" that could make it break.

    0 讨论(0)
提交回复
热议问题