【问题标题】:PHP:PCRE: How to replace repeatable charPHP:PCRE: 如何替换可重复字符
【发布时间】:2011-08-27 05:30:54
【问题描述】:

例如我有以下字符串:

a_b__c___d____e

如何将 char _ 替换为 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

谢谢!

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

【问题讨论】:

    标签: php regex preg-replace pcre


    【解决方案1】:

    这是另一个使用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);
    }
    

    【讨论】:

      【解决方案2】:
      $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);
      

      【讨论】:

        【解决方案3】:

        这是内联解决方案:

        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);
        

        【讨论】:

          【解决方案4】:

          不鼓励使用修饰符 e 引用 php.net documenation

          自 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]... */
          

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


          preg_replace_callback 从 4.0.5 版本开始可用,但 function($matches) {} 是一个匿名函数,实际上是更新的语言功能,要运行此代码,您需要 5.3.0 或更高版本的 PHP。

          【讨论】:

            【解决方案5】:

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

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

            demo

            对于 n=2:

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

            对于 n=3:

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

            对于 n=4:

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

            等等

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

            【讨论】:

              猜你喜欢
              • 2013-10-24
              • 2014-07-16
              • 1970-01-01
              • 2013-05-18
              • 2019-05-20
              • 2021-03-26
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多