【问题标题】:Replace all substring instances with a variable string用可变字符串替换所有子字符串实例
【发布时间】:2011-09-29 14:35:35
【问题描述】:

如果你有字符串

'Old string Old more string Old some more string'

你想得到

'New1 string New2 more string New3 some more string'

你会怎么做?

换句话说,您需要用变量字符串 'New'.$i 替换所有 'Old' 实例。怎么办?

【问题讨论】:

    标签: php string replace


    【解决方案1】:

    来自str_replace 上的 PHP 手册:

    用替换字符串替换所有出现的搜索字符串

    mixed str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
    

    搜索

    正在搜索的值,也称为 needle。一个数组可以用来指定多个针。

    替换

    替换找到的搜索值的替换值。一个数组可以用来指定多个替换。

    主题

    被搜索和替换的字符串或数组,也称为 haystack

    如果subject是一个数组,则对subject的每一项进行查找替换,返回值也是一个数组。

    计数

    如果通过,这将设置为执行的替换次数。

    【讨论】:

    • @Downvoter:虽然 Ovais 没有解释这一点,但str_replace 确实接受了多个替换参数。
    • 这个答案本身并没有错。您只需要在替换之前计算变量,而不是在回调函数中即时计算。
    • 但是它不能处理这样的情况,根据出现的次数,一个$search应该被不同的$replace替换。根据问题:它将始终用相同的字符串替换每次出现的Old
    • @KingCrunch:啊,真的。当我意识到这一点时正在制定a demo
    【解决方案2】:

    使用preg_replace_callback

    $count = 0;
    $str = preg_replace_callback(
        '~Old~',
        create_function('$matches', 'return "New".$count++;'),
        $str
    );
    

    【讨论】:

    • 您的匿名函数将无法访问此处的$count
    • anubhava 想说的是:它不起作用(请不要用全局变量“修复”它:X)
    • 好的,我明白了。感谢 KingCrunch,那么我也为您的迭代解决方案投票。
    【解决方案3】:

    不需要正则表达式的迭代解决方案:

    $str = 'Old string Old more string Old some more string';
    $old = 'Old';
    $new = 'New';
    
    $i = 1;
    
    $tmpOldStrLength = strlen($old);
    
    while (($offset = strpos($str, $old, $offset)) !== false) {
      $str = substr_replace($str, $new . ($i++), $offset, $tmpOldStrLength);
    }
    

    strpos() 中的$offset 只是一点点微优化。我不知道是否值得(事实上我什至不知道,如果它改变了什么),但我们的想法是我们不需要在已经处理的子字符串中搜索$old

    Demo

    Old string Old more string Old some more string
    New1 string New2 more string New3 some more string
    

    【讨论】:

    • 这不是优化,没有它该功能将无法工作。您需要指定偏移量替换开始于。
    • 错了(我测试了它;这是我的第一个建议):strpos() 中的 $offset 是可选的。因为$old从左到右替换strpos()总是返回$old最左边出现的索引,每次替换都会向前移动。这里的$offset 应该避免,我们在字符串的部分中寻找$old不能 再包含$old
    • @KingCrunch:我指的是 substr_replace() 的 $offset,我读的不好。对于strpos,我觉得是个好主意,尤其是长字符串。
    • @Marko:我在下面添加了一个函数,可以用于回调和多个替换。
    【解决方案4】:

    用途:

    $str = 'Old string Old more string Old some more string';
    $i = 1;
    while (preg_match('/Old/', $str)) {
        $str = preg_replace('/Old/', 'New'.$i++, $str, 1);
    }
    echo $str,"\n";
    

    输出:

    New1 string New2 more string New3 some more string
    

    【讨论】:

      【解决方案5】:

      我有一些类似的解决方案,例如 KingCrunch's,但正如他已经回答的那样,我想知道带有替换回调的 str_replace 变体并想出了这个 (Demo):

      $subject = array('OldOldOld', 'Old string Old more string Old some more string');
      $search = array('Old', 'string');
      $replace = array(
          function($found, $count) {return 'New'.$count;},
          function($found, $count) {static $c=0; return 'String'.(++$c);}
      );
      $replace = array();
      
      print_r(str_ureplace($search, $replace, $subject));
      
      /**
       * str_ureplace
       *
       * str_replace like function with callback
       *
       * @param string|array search
       * @param callback|array $replace
       * @param string|array $subject
       * @param int $replace_count
       * @return string|array subject with replaces, FALSE on error.
       */
      function str_ureplace($search, $replace, $subject, &$replace_count = null) {
          $replace_count = 0;
      
          // Validate input
          $search = array_values((array) $search);
          $searchCount = count($search);
          if (!$searchCount) {
              return $subject;
          }
          foreach($search as &$v) {
              $v = (string) $v;
          }
          unset($v);
          $replaceSingle = is_callable($replace);
          $replace = $replaceSingle ? array($replace) : array_values((array) $replace);
          foreach($replace as $index=>$callback) {
              if (!is_callable($callback)) {
                  throw new Exception(sprintf('Unable to use %s (#%d) as a callback', gettype($callback), $index));
              }
          }
      
          // Search and replace
          $subjectIsString = is_string($subject);
          $subject = (array) $subject;
          foreach($subject as &$haystack) {
              if (!is_string($haystack)) continue;
              foreach($search as $key => $needle) {
                  if (!$len = strlen($needle))
                      continue;
                  $replaceSingle && $key = 0;
                  $pos = 0;
                  while(false !== $pos = strpos($haystack, $needle, $pos)) {
                      $replaceWith = isset($replace[$key]) ? call_user_func($replace[$key], $needle, ++$replace_count) : '';
                      $haystack = substr_replace($haystack, $replaceWith, $pos, $len);
                  }
              }
          }
          unset($haystack);
      
          return $subjectIsString ? reset($subject) : $subject;
      }
      

      【讨论】:

      • 你不需要区分,如果$search是一个字符串,还是一个数组:codepad.org/H4MZCiLd 不过,我觉得可能有用。
      • @KingCrunch:感谢您的通知。我在煮的时候也跑过去。刚刚更新到一个新版本,它将数组作为任何参数以更好地匹配 PHP 的行为,甚至现在在错误时返回 false 并在参数错误的情况下发出通知(它可能会检查有效的回调,但仍然缺失)。
      • 与 str_replace 相比,行为之间更相似的另一个更新。现在在 str_replace 会发生致命错误的地方抛出异常,并且替换现在类似于 str_replace 的做法(reg. number of replacements)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-16
      • 2014-03-14
      • 2017-09-04
      • 2012-11-14
      • 2017-03-23
      • 1970-01-01
      相关资源
      最近更新 更多