【问题标题】:How to add spaces around a substring if spaces aren't already there yet?如果空格还没有,如何在子字符串周围添加空格?
【发布时间】:2012-09-15 03:34:57
【问题描述】:

示例输入字符串:test:)test:)test:) :) test:p test
想要的输出字符串:test :) test :) test :) :) test :p test

正如您在上面的示例中所见,我想解析字符串并生成一个输出字符串,并在所有预定义的笑脸代码周围添加空格。

我试图通过几个循环来做到这一点,但最终它并没有像预期的那样 100% 工作,而且在大型文档上速度非常慢。

所以我想知道用 PHP 进行这种解析的最好和最有效的方法是什么?

【问题讨论】:

  • 正则表达式。学习它们,享受它们,并发现在preg_replace一行中很容易做到这一点
  • 我之前尝试过使用 preg_replace() 执行此操作,但由于某种原因它不起作用。你能帮帮我吗?
  • @Prinzhorn 我尝试使用 '$text=preg_replace('/([^ ]):\)([^ ])/i', '$1 :) $2', $text)' 但是不起作用。知道它有什么问题吗?
  • 为什么不加空格,然后用一个空格替换多个空格

标签: php parsing spaces emoticons


【解决方案1】:

嵌套替换:

preg_replace("/\s\s+/", " ", 
    str_replace( Array( ":)", ":p" ),
        Array( " :) ", " :p " ), $str) );

【讨论】:

    【解决方案2】:
    <?php
    
    $lspace =   str_replace(":"," :","test:)test:)test:) :) test:p");
    $rspace =    str_replace(")",") ",$lspace);
    $out    =    preg_replace("/\s\s+/"," ",$rspace);
    
    
    echo $out;
    ?>
    

    输出:test :) test :) test :) :) test :p

    【讨论】:

      【解决方案3】:

      您可以使用str_replace 函数代替正则表达式。 PHP函数str_replace可以接收数组作为参数,你可以试试这个:

      $input = 'test:)test:)test:) :) test:p test';
      $smileys = array( ':)', ':p' );
      $smileys_with_spaces = array( ' :)', ' :p' );
      $output = str_replace( $smileys_with_spaces, $smileys, $input ); // test:) :) -> test:):)
      $output = str_replace( $smileys, $smileys_with_spaces, $input ); // test:):) -> test :) :)
      

      【讨论】:

      • 这看起来不像一个可用的解决方案,因为它会添加过多的空格。例如,它会在周围已经有空格的笑脸代码中添加空格。
      • 正则表达式是更好的方法。 @xdazz 给出了更合适的解决方案。
      • 只需删除str_replace( '&lt;space&gt;&lt;space&gt;', '&lt;space&gt;', $input );的多余空格。
      【解决方案4】:

      试试:

      $str = "test:)test:)test:) :) test:p test";
      $str = preg_replace('/(?<=[a-z])(?=[^a-z\s])|(?<=[^a-z]{2})(?=[a-z])/', ' ', $str);
      

      【讨论】:

      • 当两个笑脸代码彼此相邻时,这个将不起作用。所以 $str 是 ":):)",它不会添加任何空格
      【解决方案5】:

      更新支持 N 个笑脸

      $smile = array(':)', ':p');
      
      //Escape smiley chars for use in rx
      foreach($smile as &$s) {
          $s = preg_quote($s, '/');
      }unset($s);
      
      $rx = implode('|', $smile);
      
      $str = 'test:)test:)test:) :) test:p test';
      
      $str = preg_replace('/ *('.$rx.') */', ' $1 ', $str);
      $str = preg_replace('/('.$rx.') +/', '$1 ', $str);
      
      echo $str;
      

      【讨论】:

      • 这个可以,只是如果两个笑脸代码彼此相邻,它会添加太多空格。例如,“:):)”将变为“:):)”,而在本例中我需要“:):)”。
      • 知道如何解决这个问题吗?
      • 此更新仍然不会修复字符串开头或结尾处过多的空格。而且我不能使用 trim() 因为如果原件在开头或结尾有空格,它必须保持这种状态。
      • 示例输入很简单:“:):)”。这将在您的代码的开头和结尾获得一个空格。但我只需要它来获得 1 个额外的空间:仅在笑脸代码之间。
      【解决方案6】:

      如果您也不想在开头/结尾有多余的空格,试试这个:

      $str = ':):)test:)test:)test:) :) test:p:) test';
      $codes = array(
          ':)', ':p', // Add smileys here.
      );
      
      // We build the $regexp automatically
      $regexp = array();
      foreach($codes as $smiley)
          $regexp[] = preg_quote($smiley, '#');
      $regexp = implode('|', $regexp);
      // Afterwards, we might replace the above with $regexp = 'VERYCOMPLICATEDSYNTAX';
      
      // Split the string at smileys, trimming the smileys as we go,
      // and returning an array of smiley-and-non-smiley parts, except for empty ones
      $parts = preg_split("#\s*($regexp)\s*#", $str, -1,
          PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
      
      // The new delimiter is a single space.
      $str = implode(' ', $parts);
      

      请注意,我使用了空白匹配器 \s 而不是文字空间;如果您在原始字符串中有换行符,这可能会产生不需要的结果。如果是这种情况,请将 "\s" 替换为 " " 文字空格。

      【讨论】:

        【解决方案7】:

        应该有一个更优雅的解决方案,但下面的代码应该可以工作

        $patterns = array();
        $replacements = array();
        
        $str = ':) test :)test:) test :)';
        
        $smileys = array(':)', ':p');
        
        foreach($smileys as &$s) {
            $s = preg_quote($s, '/');
        }unset($s);
        $escaped_smiley = implode('|', $smileys);
        
        $patterns[] = '/([^\s])('.$escaped_smiley.')([^\s])/'; // no spaces
        $patterns[] = '/([\s])('.$escaped_smiley.')([^\s])/';  // space on left
        $patterns[] = '/([^\s])('.$escaped_smiley.')([\s])/';  // space on right
        
        $patterns[] = '/^('.$escaped_smiley.')([\s])/';   // line starting, space succeding
        $patterns[] = '/^('.$escaped_smiley.')([^\s])/';  // line starting, no space
        $patterns[] = '/([\s])('.$escaped_smiley.')$/';   // line ending, space preceeding
        $patterns[] = '/([^\s])('.$escaped_smiley.')$/';  // line ending, no space
        
        $replacements[] = '$1 $2 $3'; // no spaces 
        $replacements[] = '$1$2 $3';  // space on left
        $replacements[] = '$1 $2$3';  // space on right
        
        $replacements[] = ' $1$2';    // line starting
        $replacements[] = ' $1 $2';   // line starting
        $replacements[] = '$1$2 ';    // line ending
        $replacements[] = '$1 $2 ';   // line ending
        
        
        $result = preg_replace($patterns, $replacements, $str);
        echo str_replace(' ', '^', $result);
        

        [使用从@Prinzhorn 借来的代码进行编辑]

        【讨论】:

        • 这会导致输入字符串失败,例如 ':)test:)test:)test:)'
        • 输出是 :)test :) test :) test:) .. 注意第一个表情符号代码末尾和最后一个表情符号代码之前缺少的空格。
        • @Erik 编辑了代码以考虑行的开始和结束。还使用@Prinzhorn 的implode 删除了foreach 循环,并用引用foreach 循环替换了引用的笑脸。
        【解决方案8】:

        如果您还没有解决问题,我想出了一个可行的解决方案。首先用空格作为分隔符来分解字符串,用额外的空格替换笑脸,然后用 implode 重新连接它们。

        检查php fiddle 以了解实施情况。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-07-06
          • 1970-01-01
          • 2016-05-31
          • 1970-01-01
          • 1970-01-01
          • 2019-09-25
          • 2016-09-18
          • 2022-06-20
          相关资源
          最近更新 更多