如果你想走完全的矫枉过正的路线,你可以重复使用 Wordpress 的正则表达式和处理。
例如:
<?php
$res = extract_specific_shortcode('links', $teststring = '[links label="Label" url="https://nisamerica.com/" external="yes" /] '."\n".
'[links label="Label2" url="https://google.com/" external="no"]content[/links]' );
print_r($res);
function extract_specific_shortcode( $tagname, $content ) {
$tagname_regex = preg_quote($tagname, '/');
$wp_shortcode_atts = function( $text ) {
$atts = array();
$pattern = '/([\w-]+)\s*=\s*"([^"]*)"(?:\s|$)|([\w-]+)\s*=\s*\'([^\']*)\'(?:\s|$)|([\w-]+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|\'([^\']*)\'(?:\s|$)|(\S+)(?:\s|$)/';
$text = preg_replace( "/[\x{00a0}\x{200b}]+/u", ' ', $text );
if ( preg_match_all( $pattern, $text, $match, PREG_SET_ORDER ) ) {
foreach ( $match as $m ) {
if ( ! empty( $m[1] ) ) {
$atts[ strtolower( $m[1] ) ] = stripcslashes( $m[2] );
} elseif ( ! empty( $m[3] ) ) {
$atts[ strtolower( $m[3] ) ] = stripcslashes( $m[4] );
} elseif ( ! empty( $m[5] ) ) {
$atts[ strtolower( $m[5] ) ] = stripcslashes( $m[6] );
} elseif ( isset( $m[7] ) && strlen( $m[7] ) ) {
$atts[] = stripcslashes( $m[7] );
} elseif ( isset( $m[8] ) && strlen( $m[8] ) ) {
$atts[] = stripcslashes( $m[8] );
} elseif ( isset( $m[9] ) ) {
$atts[] = stripcslashes( $m[9] );
}
}
// Reject any unclosed HTML elements.
foreach ( $atts as &$value ) {
if ( false !== strpos( $value, '<' ) ) {
if ( 1 !== preg_match( '/^[^<]*+(?:<[^>]*+>[^<]*+)*+$/', $value ) ) {
$value = '';
}
}
}
} else {
$atts = ltrim( $text );
}
return $atts;
};
// Taken from wordpress
$regex = '/\\[' // Opening bracket.
. '(\\[?)' // 1: Optional second opening bracket for escaping shortcodes: [[tag]].
. "($tagname_regex)" // 2: Shortcode name.
. '(?![\\w-])' // Not followed by word character or hyphen.
. '(' // 3: Unroll the loop: Inside the opening shortcode tag.
. '[^\\]\\/]*' // Not a closing bracket or forward slash.
. '(?:'
. '\\/(?!\\])' // A forward slash not followed by a closing bracket.
. '[^\\]\\/]*' // Not a closing bracket or forward slash.
. ')*?'
. ')'
. '(?:'
. '(\\/)' // 4: Self closing tag...
. '\\]' // ...and closing bracket.
. '|'
. '\\]' // Closing bracket.
. '(?:'
. '(' // 5: Unroll the loop: Optionally, anything between the opening and closing shortcode tags.
. '[^\\[]*+' // Not an opening bracket.
. '(?:'
. '\\[(?!\\/\\2\\])' // An opening bracket not followed by the closing shortcode tag.
. '[^\\[]*+' // Not an opening bracket.
. ')*+'
. ')'
. '\\[\\/\\2\\]' // Closing shortcode tag.
. ')?'
. ')'
. '(\\]?)/i'; // 6: Optional second closing brocket for escaping shortcodes: [[tag]].
// phpcs:enable
preg_match_all($regex, $content, $matches, PREG_SET_ORDER);
$set = [];
foreach($matches as $match) {
$set[] = [
'fullmatch' => $match[0],
'attributes' => $wp_shortcode_atts($match[3]),
];
}
return $set;
}
产生以下输出:
Array
(
[0] => Array
(
[fullmatch] => [links label="Label" url="https://nisamerica.com/" external="yes" /]
[attributes] => Array
(
[label] => Label
[url] => https://nisamerica.com/
[external] => yes
)
)
[1] => Array
(
[fullmatch] => [links label="Label2" url="https://google.com/" external="no"]content[/links]
[attributes] => Array
(
[label] => Label2
[url] => https://google.com/
[external] => no
)
)
)
以上代码来源于以下函数:
与发布的其他解决方案一样,WordPress 将其属性映射分为两部分:收集键和值,然后将它们组合在一起。他们的正则表达式比这里展示的要多一些,因为它处理的边缘情况当然要多一些。