PHP:PCRE:如何替换可重复的char

时间:2011-05-17 12:59:46

标签: php regex preg-replace pcre

例如我有以下字符串:

a_b__c___d____e

如何preg_replace char _ to char' - ',但仅当部分'__...'包含多于N重复_时。

我希望你理解我))

source: a_b__c___d____e
cond: change '_' where 2 or more
result: a_b--c---d----e

source: a_b__c___d____e_____f
cont: change '_' where 4 or more
result: a_b__c___d----e-----f

谢谢!

P.S。有趣的解决方案,不使用循环。如何用循环实现它(我认为)知道任何人。只需一个正则表达式和preg_replace。

5 个答案:

答案 0 :(得分:2)

这是使用e修饰符的另一个修饰符:

 $str = 'a_b__c___d____e_____f';
 echo preg_replace('/_{4,}/e', 'str_repeat("-", strlen("$0"))', $str);

4替换为您需要的号码。或者作为功能:

function repl($str, $char, $times) {
    $char = preg_quote($char, '/');
    $times = preg_quote($times, '/');
    $pattern = '/' . $char . '{' . $times . ',}/e',
    return preg_replace($pattern, 'str_repeat("-", strlen("$0"))', $str);
}

答案 1 :(得分:1)

$source = 'a_b__c___d____e_____f';
function yourfunc($param)
{
    $count  = strlen($param);
    $return = '';
    for ($i = 0; $i < $count; $i++)
    {
        $return .= '-';
    }
    return $return;
}
echo preg_replace('#(_{4,})#e', 'yourfunc("$1");', $source);

没有回调函数和循环的解决方案更难阅读。

preg_replace('#(_{4,})#e', 'implode("", array_pad(array(), strlen("$1"), "-"));', $source);

答案 2 :(得分:1)

这是内联解决方案:

preg_replace('/(_{2,})/ie', 'str_repeat("-",strlen("$1"));', $source);

和可重复使用的功能:

$source = 'a_b__c___d____e_____f';


    function replace_repeatable($source,$char,$replacement,$minrepeat = 2)
    {
          return preg_replace('/(' . preg_quote($char) . '{' . $minrepeat . ',})/ie', 'str_repeat("' . $replacement . '",strlen("$1"));', $source);
    }

    $b = replace_repeatable($source,'_','-',4);

答案 3 :(得分:0)

提及php.net documenation使用修饰符e是不鼓励的,

  

自PHP 5.5.0起,此功能已被弃用。非常不鼓励依赖此功能。

所以我们最好不要使用这个修饰符来实现我们的目标。


这是基于最新PHP工具的解决方案:

$source = 'a_b__c___d____e';

echo preg_replace_callback( "%(_{2,})%i", function($matches) {return str_repeat( "-", strlen($matches[1]) ); }, $source );
/* in callback function matches[0] is whole matched pattern, groups go like this matches[1],matches[2]... */

即使在我们的PHP环境中仍然可以使用e,通常最好使用回调函数 - 感谢回调我们避免了addslashes()函数和字符串求值的相当不安全的组合,因为运行preg_replace与提到修饰符一次参与两个动作。


自版本4.0.5起,preg_replace_callback已经可用,但function($matches) {}是一个匿名函数,实际上是更新的语言功能,运行此代码,你需要在5.3版中使用PHP。 0或更新

答案 4 :(得分:0)

您可以使用 \G 锚点逐个替换破折号,以确保从第一个 -(后跟 n-1 个其他 -)的位置到最后一个的位置连续一。这样你只需要检查第一个后面的破折号的数量:

echo preg_replace('~\G(?!^)_|_(?=_)~', '-', $str);

demo

对于 n=2:

\G(?!^)_|_(?=_)

对于 n=3:

\G(?!^)_|_(?=_{2})

对于 n=4:

\G(?!^)_|_(?=_{3})

第一个分支 \G(?!^)_ 只有在前一个位置匹配成功时才会成功。换句话说,这意味着这个分支将失败,直到下一个第二个分支成功。 第二个分支 _(?=_{n-1}) 专用于第一个下划线。它使用前瞻断言检查以下下划线的数量。