【问题标题】:Convert backslash-delimited string into an associative array将反斜杠分隔的字符串转换为关联数组
【发布时间】:2011-07-14 12:05:52
【问题描述】:

我有一个这样的字符串:

key1\value1\key2\value2\key3\value3\key4\value4\key5\value5

我希望它是一个关联数组,这样我就可以做到:

echo $myArray['key1']; // prints value1
echo $myArray['key3']; // prints value3
//etc...

我知道我可以在反斜杠上爆炸,但不知道如何从那里开始。

【问题讨论】:

    标签: php arrays string associative-array explode


    【解决方案1】:

    通过preg_match_allarray_combine 使用简单的regex 通常是最短和最快的选择:

     preg_match_all("/([^\\\\]+)\\\\([^\\\\]+)/", $string, $p);
     $array = array_combine($p[1], $p[2]);
    

    现在这当然是一个特例。 keysvalues 都由 \ 反斜杠分隔,它们都是成对的。由于必要的双重转义,正则表达式也有点长。

    不过,这个方案可以推广到其他key:value, 风格的字符串。

    不同的key:value, 分隔符

    常见的变体包括 := 作为键/值分隔符,以及 & 等对分隔符。在这种情况下,正则表达式变得相当明显(带有/x 标志以提高可读性):

     #                    ↓    ↓    ↓
     preg_match_all("/ ([^:]+) : ([^,]+) /x", $string, $p);
     $array = array_combine($p[1], $p[2]);
    

    这使得将:, 交换为其他分隔符变得非常容易。

    • 等号 = 而不是 : 冒号。
    • 例如 \\t 作为对分隔符(制表符分隔的键:值列表)
    • 经典的&; 作为键=值对之间的分隔符。
    • 或者只是 \\s 空格或 \\n 换行符。

    允许不同的分隔符

    您可以通过在键/值/对之间允许不同的分隔符来使其更加灵活/宽容:

     #                    ↓      ↓       ↓
     preg_match_all("/ ([^:=]+) [:=]+ ([^,+&]+) /x", $string, $p);
    

    key=value,key2:value2++key3==value3 都可以工作。这对于更人性化的用户(AKA 非技术用户)来说是有意义的。

    约束字母数字键

    通常您可能想要禁止除经典的key 标识符之外的任何内容。只需使用\w+ 字串模式让正则表达式跳过不需要的事件:

     #                   ↓   ↓    ↓
     preg_match_all("/ (\w+) = ([^,]+) /x", $string, $p);
    

    这是最简单的白名单方法。如果 OTOH 你想预先断言/约束整个键/值字符串,然后制作一个单独的preg_match("/^(\w+=[^,]+(,|$))+/", …

    去除空格或引号

    您可以跳过一些后处理步骤(例如键和值上的trim),只需添加一点点:

     preg_match_all("/ \s*([^=]+) \s*=\s* ([^,]+) (?<!\s) /x", $string, $p);
    

    或者例如可选引号:

     preg_match_all("/ \s*([^=]+) \s*=\s* '? ([^,]+) (?<![\s']) /x", $string, $p);
    

    INI 样式提取

    您可以制作一个基线 INI 文件提取方法:

     preg_match_all("/^ \s*(\w+) \s*=\s* ['\"]?(.+?)['\"]? \s* $/xm", $string, $p);
    

    请注意,这只是常见 INI 方案的粗略子集

    替代方案:parse_str()

    如果你已经有一个key=value&amp;key2=value2 字符串,那么parse_str 就像一个魅力。但是通过将它与strtr 结合使用,甚至可以处理不同的其他分隔符:

     #                         ↓↓    ↑↑
     parse_str(strtr($string, ":,", "=&"), $pairs);
    

    这有几个自己的优点和缺点

    • 甚至比两行正则表达式方法更短。
    • 预定义了众所周知的转义机制,例如 %2F 用于特殊字符)。
    • 不允许使用不同的分隔符,或内部未转义的分隔符。
    • 自动将keys[]= 转换为数组,您可能需要也可能不需要。

    备选方案:explode + foreach

    您会发现很多manual key/value string expansion 的示例。虽然这通常是更多的代码。由于优化假设,explode 在 PHP 中有些过度使用。然而,由于手动 foreach 和数组集合,分析后通常会变慢。

    【讨论】:

    • 如果您的字符串包含这样的制表符跳转,正则表达式会是什么样子:key1=value1\tkey2=value2\tkey3=value3?
    • @EchtEinfachTV 更像这样:stackoverflow.com/questions/168171/… - 尽管有更简单的方法(将\t 替换为&amp;,然后是str_parse(),或使用正则表达式\t(\w+)=(\w+) 或其他东西)。但是,如果您有不同的来源,请发布一个新问题。
    • @mario 谢谢,我偶然发现了 parse_str() 并现在使用它: // 将制表符跳转转换为 & 以便能够使用查询函数 $toURL = str_replace("\t","&amp;",$keysValues); // 解析为 URL parse_str($toURL, $data); //数组$postid = $data['postid'];中的访问键
    【解决方案2】:

    这样的事情怎么样:

    $str = 'key1\value1\key2\value2\key3\value3\key4\value4\key5\value5';
    $list = explode('\\', $str);
    
    $result = array();
    for ($i=0 ; $i<count($list) ; $i+=2) {
        $result[ $list[$i] ] = $list[$i+1];
    }
    
    var_dump($result);
    

    这会让你:

    array
      'key1' => string 'value1' (length=6)
      'key2' => string 'value2' (length=6)
      'key3' => string 'value3' (length=6)
      'key4' => string 'value4' (length=6)
      'key5' => string 'value5' (length=6)
    


    基本上,这里的想法是:

    • 拆分字符串
    • 这将为您提供一个数组,例如'key1', 'value1', 'key2', 'value2', ...
    • 然后,迭代这个列表,跳跃为 2,每次使用:
      • 一个元素作为key——$i指向的那个
      • 紧随其后的那个作为值——$i+1指向的那个

    【讨论】:

      【解决方案3】:

      我对 RegExp 不太擅长,但是这一行代码怎么样

      parse_str(preg_replace("/key(.*?)\\value(.*?)(\\|$)/", "key$1=value$2&", $input_lines), $output);
      

      【讨论】:

        【解决方案4】:

        分割成段并以 2 为增量循环。

        $str = 'php\127\typescript\12\jquery\120\angular\50';
        $segments = explode('\\', $str);
        $data = [];
        for ($i = 0, $count = count($segments) - 1; $i < $count; $i += 2) {
            $data[$segments[$i]] = $segments[$i + 1];
        }
        

        输出

        array(4) {
          'php'        => string(3) "127"
          'typescript' => string(2) "12"
          'jquery'     => string(3) "120"
          'angular'    => string(2) "50"
        }
        

        【讨论】:

          【解决方案5】:

          @Wasim 的回答是哪个

          1. 不像发布的那样工作,并且
          2. 其中@mario 列出了使用注意事项

          可以通过混合使用否定字符类和转义文字反斜杠来建立查询字符串来改进/变得更加灵活。

          代码:(Demo)

          parse_str(preg_replace('/([^\\\\]+)\\\\([^\\\\]+)\\\\?/', '$1=$2&', $string), $output);
          var_export($output);
          

          输出:

          array (
            'key1' => 'value1',
            'key2' => 'value2',
            'key3' => 'value3',
            'key4' => 'value4',
            'key5' => 'value5',
          )
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-11-19
            • 2012-10-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多