【问题标题】:PHP preg_split if not inside curly bracketsPHP preg_split 如果不在大括号内
【发布时间】:2010-11-24 00:45:06
【问题描述】:

我正在使用 PHP 制作脚本语言解释器。我有这个脚本语言的代码:

write {Hello, World!} in either the color {blue} or {red} or {#00AA00} and in either the font {Arial Black} or {Monaco} where both the color and the font are determined randomly

(是的,很难相信,但这就是语法)

我必须使用哪个正则表达式来分割它(用空格分割),但前提是不在大括号内。所以我想把上面的代码变成这个数组:

  1. 你好,世界!
  2. 要么
  3. 颜色
  4. 蓝色
  5. 红色
  6. #00AA00
  7. 要么
  8. 字体
  9. 宋体黑
  10. 摩纳哥
  11. 在哪里
  12. 两者都有
  13. 颜色
  14. 字体
  15. 确定
  16. 随机

(大括号内的字符串以粗体显示) 花括号内的字符串每个必须是一个元素。所以 {Hello, World!} 不能是: 1. 你好, 2.世界!

我该怎么做?

提前致谢。

【问题讨论】:

    标签: php regex programming-languages preg-split


    【解决方案1】:

    如何使用这样的东西:

    $str = 'write {Hello, World!} in either the color {blue} or {red} or {#00AA00} and in either the font {Arial Black} or {Monaco} where both the color and the font are determined randomly';
    
    $matches = array();
    preg_match_all('#\{.*?\}|[^ ]+#', $str, $matches);
    
    var_dump($matches[0]);
    

    这会得到你:

    array
      0 => string 'write' (length=5)
      1 => string '{Hello, World!}' (length=15)
      2 => string 'in' (length=2)
      3 => string 'either' (length=6)
      4 => string 'the' (length=3)
      5 => string 'color' (length=5)
      6 => string '{blue}' (length=6)
      7 => string 'or' (length=2)
      8 => string '{red}' (length=5)
      9 => string 'or' (length=2)
      10 => string '{#00AA00}' (length=9)
      11 => string 'and' (length=3)
      12 => string 'in' (length=2)
      13 => string 'either' (length=6)
      14 => string 'the' (length=3)
      15 => string 'font' (length=4)
      16 => string '{Arial Black}' (length=13)
      17 => string 'or' (length=2)
      18 => string '{Monaco}' (length=8)
      19 => string 'where' (length=5)
      20 => string 'both' (length=4)
      21 => string 'the' (length=3)
      22 => string 'color' (length=5)
      23 => string 'and' (length=3)
      24 => string 'the' (length=3)
      25 => string 'font' (length=4)
      26 => string 'are' (length=3)
      27 => string 'determined' (length=10)
      28 => string 'randomly' (length=8)
    

    你只需要遍历这些结果;以 { 开头并以 } 结尾的将是您的“重要”词,其余的将是其他词。


    在评论后编辑:识别重要单词的一种方法是这样的:

    foreach ($matches[0] as $word) {
        $m = array();
        if (preg_match('#^\{(.*)\}$#', $word, $m)) {
            echo '<strong>' . htmlspecialchars($m[1]) . '</strong>';
        } else {
            echo htmlspecialchars($word);
        }
        echo '<br />';
    }
    

    或者,就像你说的,使用 strpos 和 strlen 也可以;-)

    【讨论】:

    • 感谢它的工作!现在我只删除 { 和 } 如果它们在位置 0 和 strlen(arr[a]) - 1
    【解决方案2】:

    顺序重要吗?如果不是,您可以提取所有 {},删除它们,然后对剩余的字符串进行操作。

    【讨论】:

    • 是的,因为 {Hello, World!} 也可能是 {This is an English word which is very often used: in} 而我不能做 continue; 当它看到有“in”这个词时。
    【解决方案3】:

    我会使用preg_replace_callback 替换它们。通过回调,您可以跟踪订单并将其替换为 %var1%、%var2% 等。

    我认为没有办法通过空格爆炸,但在不事先修改字符串的情况下,在大括号中没有。

    【讨论】:

      【解决方案4】:

      这可以在没有正则表达式的情况下迭代完成。您遍历整个字符串。你把每个字符都放在一个临时变量中,除非你找到一个空格。找到空格后,将临时变量的内容放入数组中,清空,然后继续。

      如果找到括号,则设置一个布尔值,然后将所有内容放入 temp var,直到找到右括号。以此类推。

      <?php
      $string = "write {Hello, World!} in either the color {blue} or {red} or {#00AA00} and in either the font {Arial Black} or {Monaco} where both the color and the font are determined randomly";
      $bracket = false;
      $words = array();
      $temp = "";
      
      for($i = 0; $i < strlen($string); $i++){    
          $char = $string[$i]
          if($bracket){
              $temp .= $char;
              if($char == "}"){
                  $bracket = false;
                  $words[] = $temp;
              }
          }
          else{
              if($char == " "){
                  if($temp != ""){
                      $words[] = $temp;
                      $temp = "";
                  }
              }
              elseif($char == "{"}{
                  $temp .= $char;
                  $bracket = true;
              }
              else{
                  $temp .= $char;
              }
          }
      }
      ?>
      

      代码未经测试。

      【讨论】:

        【解决方案5】:

        您想在大括号中不包含的所有空格上进行拆分。

        匹配大括号表达式或非空白字符序列,然后使用\K 忽略这些匹配项,然后使用以下空格作为分隔符。

        代码:(Demo)

        $text = 'write {Hello, World!} in either the color {blue} or {red} or {#00AA00} and in either the font {Arial Black} or {Monaco} where both the color and the font are determined randomly';
        
        var_export(preg_split('~({[^}]*}|\S+)\K ~', $text));
        

        附言你可以用像这样的强标签替换花括号:https://3v4l.org/fXrgE

        p.p.s.您可以使用preg_replace_callback() 构建您的确切排序列表:(Demo)

        $text = 'write {Hello, World!} in either the color {blue} or {red} or {#00AA00} and in either the font {Arial Black} or {Monaco} where both the color and the font are determined randomly';
        
        echo "<ol>" , preg_replace_callback('~{([^}]*)}|(\S+)~', function($m) {
                if (!isset($m[2])) {
                    return "<li><strong>{$m[1]}</strong></li>\n";
                }
                return "<li>{$m[2]}</li>\n";
            },
            $text) , "<ol>";
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-05-02
          • 2011-05-31
          • 2022-01-02
          • 1970-01-01
          • 1970-01-01
          • 2023-03-25
          • 2023-03-19
          • 1970-01-01
          相关资源
          最近更新 更多