内部循环的preg_replace替换了最后一个匹配而不是每个匹配

时间:2014-04-22 20:33:28

标签: php foreach preg-match-all

对不起标题我真的不知道怎么解释它。

我正在制作一个小的短代码功能,需要用html输出替换短代码。

preg_match_all找到我需要的所有内容,但preg_replace一遍又一遍地替换相同的匹配。 这是演示 https://eval.in/139727

我确信我在那些foreach循环中搞得一团糟,但却无法弄明白。

$text = 'Some text and some [link link="linkhref1" text="Text1"],[link link="linkhref2" text="Text2"]';


function shortcodes($text) {
    $shortcodes = array(
        'link' => array(
            "check" => "[link",
            "type" => "link",
            "match" => "#\[link(.*?)link\=\"(.*?)\"(.*?)text\=\"(.*?)\"#Ui",
            "replace" => "/\[link(.*?)\]/s"
        )
    );
    foreach ($shortcodes as $index => $shortcode) {
        if (strpos($text, $shortcode['check']) !== false) {
            $text = shortcode_replace($shortcode, $text);
        }
    }
    return $text;
}


function shortcode_replace($shortcode, $text) {
    $replacement = '';
    preg_match_all($shortcode['match'], $text, $matches);
    switch ($shortcode['type']) {
        case "link":
            foreach ($matches[4] as $index => $match) {
                $link     = $matches[2][$index];
                $linktext = $matches[4][$index];
                $replacement .= '<a href="' . $link . '">' . $linktext . '</a>';
                $text = preg_replace($shortcode['replace'], $replacement, $text);
            }
    }

    return $text;
}



echo shortcodes($text);

任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:1)

正则表达式中存在问题我已经改变了它。你也不需要preg_replace。

<?php
$text = 'Some text and some [link link="linkhref1" text="Text1"],[link link="linkhref2" text="Text2"]';


function shortcodes($text) {
    $shortcodes = array(
        'link' => array(
            "check" => "[link",
            "type" => "link",
            "match" => "#\[link(\s+)link\=\"([^\"]+)\"(\s+)text\=\"([^\"]+)\"\]#Ui",
            "replace" => "/\[link(.*?)\]/s"
        )
    );
    foreach ($shortcodes as $index => $shortcode) {
        if (strpos($text, $shortcode['check']) !== false) {
            $text = shortcode_replace($shortcode, $text);
        }
    }
    return $text;
}


function shortcode_replace($shortcode, $text) {
    $replace = '';
    preg_match_all($shortcode['match'], $text, $matches);
    switch ($shortcode['type']) {
        case "link":
            var_dump($matches);
            foreach ($matches[4] as $index => $match) {
                $link     = $matches[2][$index];
                $linktext = $matches[4][$index];
                $replace = '<a href="' . $link . '">' . $linktext . '</a>';
                $text = str_replace($matches[0][$index], $replace, $text);
            }
    }

    return $text;
}



echo shortcodes($text);

答案 1 :(得分:0)

这是一个工作版本:

<?php
$text = 'Some text and some [link link="linkhref1" text="Text1"],[link link="linkhref2" text="Text2"]';


function shortcodes($text) {
    $shortcodes = array(
        'link' => array(
            "check" => "[link",
            "type" => "link",
            "match" => "#\[link(.*?)link\=\"(.*?)\"(.*?)text\=\"(.*?)\"#",
            "replace" => "/\[link(.*?)\]/s"
        )
    );
    foreach ($shortcodes as $index => $shortcode) {
        if (strpos($text, $shortcode['check']) !== false) {
            $text = shortcode_replace($shortcode, $text);
        }
    }
    return $text;
}


function shortcode_replace($shortcode, $text) {
    $replace = '';
    preg_match_all($shortcode['match'], $text, $matches);

    switch ($shortcode['type']) {
        case "link":
            foreach ($matches[4] as $index => $match) {
                $link     = $matches[2][$index];
                $linktext = $matches[4][$index];
                $replace .= '<a href="' . $link . '">' . $linktext . '</a>';
                $whatToReplace = '[link link="'.$link.'" text="'.$linktext.'"]';


                $text = str_replace($whatToReplace, $replace, $text);
            }
    }

    return $text;
}



echo shortcodes($text);

我不是很擅长RegExp,我修改了“匹配”以匹配所有链接(用你得到的,它没有)

您需要确定要替换的确切[link],而不是所有这些。在我看来,这是识别链接的正确方法,您也可以使用strpos()(获取字符串的开头和结尾)或查看[link start和first]的位置来识别它。

更好的选择是创建一个具有唯一值的正则表达式,它可以补偿标记之间的额外空格

希望这对你有所帮助