preg_split 短代码属性到数组

preg_split shortcode attributes into array

我想通过“preg_split”将简码解析为数组。

这是示例简码:

[contactform id="8411" label="This is \" first label" label2='This is second \' label']

这应该是结果数组:

Array
(
    [id] => 8411
    [label] => This is \" first label
    [label2] => This is second \' label
)

我有这个正则表达式:

$atts_arr = preg_split('~\s+(?=(?:[^\'"]*[\'"][^\'"]*[\'"])*[^\'"]*$)~', trim($shortcode, '[]'));

不幸的是,这仅在没有转义引号 \'\".

时有效

提前致谢!

使用 preg_split 并不总是方便或合适,尤其是当您必须处理转义引号时。因此,更好的方法是使用 preg_match_all,例如:

$pattern = <<<'EOD'
~
(\w+) \s*=
(?|
    \s* "([^"\]*(?:\.[^"\]*)*)"
  |
    \s* '([^'\]*(?:\.[^'\]*)*)'
# | uncomment if you want to handle unquoted attributes
#   ([^]\s]*)
)
~xs
EOD;

if (preg_match_all($pattern, $yourshortcode, $matches)) 
    $attributes = array_combine($matches[1], $matches[2]);

该模式使用分支重置功能 (?|...(..)...|...(...)..),为每个分支的捕获组提供相同的编号。

我在评论中谈到了 \G 锚点,如果当前位置紧接在最后一场比赛之后,这个锚点就会成功。如果您想同时从头到尾检查短代码的语法,它会很有用(否则它就完全没用了)。示例:

$pattern2 = <<<'EOD'
~
(?:
    \G(?!\A) # anchor for the position after the last match
             # it ensures that all matches are contiguous
  |
    \[(?<tagName>\w+) # begining of the shortcode
)
    \s+
    (?<key>\w+) \s*=
    (?|
        \s* "(?<value>[^"\]*(?:\.[^"\]*)*)"
      |
        \s* '([^'\]*(?:\.[^'\]*)*')
    # | uncomment if you want to handle unquoted attributes
    #   ([^]\s]*)
    )
(?<end>\s*+]\z)? # check that the end has been reached
~xs
EOD;

if (preg_match_all($pattern2, $yourshortcode, $matches) && isset($matches['end'])) 
    $attributes = array_combine($matches['key'], $matches['value']);