【问题标题】:How do I include equals and quotes when extracting from quotes in a string?从字符串中的引号中提取时如何包含等号和引号?
【发布时间】:2021-12-09 11:38:21
【问题描述】:

我有这个字符串:

$shortcode = '[csvtohtml_create include_rows="1-10" 
debug_mode="no" source_type="guess" path="largecsv" 
source_files="test?output=csv"  csv_delimiter="," ]'

我想检索属性及其值,甚至是引号内的等号或空格。

这个问题是基于这个问题:How to explode a string but not within quotes in php?

我有这个代码:

$args = preg_split('/"[^"]+"(*SKIP)(*F)|\h+/', $shortcode);
   
$attrs = [];
foreach( $args as $item )
{
    //Only use those items in array $args with = sign
    if ( strpos( $item , '=' ) !== false )
    {
        $sep = explode( '=', $item );
        $key = $sep[0];
        $value = $sep[1];
        $attrs[$key] = str_replace( '"', '', $value );
    }
}

$args = explode( '=', $sc );

我得到这个结果:(source_files without output=csv)

Array attrs
      "include_rows" => "1-10"
      "debug_mode" => "no"
      "source_type" => "guess"
      "path" => "largecsv"
      "source_files" => "test.csv?output"
      "csv_delimiter" => ","
 

我想要的结果是:

Array attrs
      "include_rows" => "1-10"
      "debug_mode" => "no"
      "source_type" => "guess"
      "path" => "largecsv"
      "source_files" => "test.csv?output=csv"
      "csv_delimiter" => ","
 

等等……

我想我应该在这里的某个地方输入等号(或者是?=),但正则表达式不是我的强项......

$args = preg_split('/"[^"]+"(*SKIP)(*F)|\h+/', $shortcode);

【问题讨论】:

    标签: php regex string


    【解决方案1】:

    可能更容易获得匹配项。然后你可以做任何事情。我把它变成一个查询字符串并解析成一个数组:

    preg_match_all('/[^\s=]+="[^"]*"/', $shortcode, $result);
    parse_str(implode('&', $result[0]), $result);
    

    现在$result 产生:

    Array
    (
        [include_rows] => "1-10"
        [debug_mode] => "no"
        [source_type] => "guess"
        [path] => "largecsv"
        [source_files] => "test?output=csv"
        [csv_delimiter] => ","
    )
    

    要去掉引号,然后将其解析为 ini 设置:

    $result = parse_ini_string(implode("\n", $result[0]));
    

    产量:

    Array
    (
        [include_rows] => 1-10
        [debug_mode] => no
        [source_type] => guess
        [path] => largecsv
        [source_files] => test?output=csv
        [csv_delimiter] => ,
    )
    

    【讨论】:

    • 也感谢您的回答!一个简单的解决方案就可以完成这项工作!我真的很感激! :-)
    【解决方案2】:

    您在爆炸等号方面走在了正确的轨道上。这个实现通过array_shift 来获取密钥,然后implodes 将数组的其余部分放在一起。

    <?php
    
    $sc = '[csvtohtml_create include_rows="1-10" 
    debug_mode="no" source_type="guess" path="largecsv" 
    source_files="test?output=csv"  csv_delimiter="," ]';
    
    $args = array_filter(array_map('trim', preg_split('/"[^"]+"(*SKIP)(*F)|\h+/', $sc)));
    array_shift($args); // remove [csvtohtml
    array_pop($args); // remove ]
    
    $output = [];
    foreach ($args as $arg) {
        $explode = explode('=', $arg);
        $key = array_shift($explode);
        $value = str_replace('"', '', implode('=', $explode)); // remove str_replace if you want to keep the extra set of quotes
        $output[$key] = $value;
    }
    
    print_r($output);
    

    结果

    Array
    (
        [include_rows] => 1-10
        [debug_mode] => no
        [source_type] => guess
        [path] => largecsv
        [source_files] => test?output=csv
        [csv_delimiter] => ,
    )
    

    【讨论】:

      【解决方案3】:

      您可以使用匹配属性名称及其值

      ([^\s=]+)=(?|"([^"]*)"|(\S+))
      

      请参阅regex demo详情

      • ([^\s=]+) - 第 1 组:除空格和 = 字符以外的一个或多个字符
      • = - = 符号
      • (?|"([^"]*)"|(\S+)) - 分支重置组:
        • "([^"]*)" - ",然后是除 " 之外的任何零个或多个字符被捕获到第 1 组,然后是 "
        • | - 或
        • (\S+) - 第 2 组:任何一个或多个非空白字符

      PHP demo

      $sc = '[csvtohtml_create include_rows="1-10" 
      debug_mode="no" source_type="guess" path="largecsv" 
      source_files="test?output=csv"  csv_delimiter="," ]';
      if (preg_match_all('~([^\s=]+)=(?|"([^"]*)"|(\S+))~', $sc, $ms)) {
          print_r(array_combine($ms[1],$ms[2]));
      }
      

      输出:

      Array
      (
          [include_rows] => 1-10
          [debug_mode] => no
          [source_type] => guess
          [path] => largecsv
          [source_files] => test?output=csv
          [csv_delimiter] => ,
      )
      

      【讨论】:

      • 感谢您的回答和良好的解释!我真的很感激! :-)
      猜你喜欢
      • 2021-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-06
      • 1970-01-01
      • 2012-07-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多