【问题标题】:Parse custom format to array将自定义格式解析为数组
【发布时间】:2017-08-06 22:47:19
【问题描述】:

我正在尝试将自定义格式的 .txt 文件转换为数组。

这是第一行的示例:

[LINETYPE]S [STARTTIME]00:00:00
[LINETYPE]M [TITLE]There For You    [PERFORMER]Martin Garrix & Troye Sivan  [MUSICID]21120  [LABEL]     
[LINETYPE]M [TITLE]Shut Up and Dance    [PERFORMER]Walk The Moon    [MUSICID]20634  [LABEL] 

这种情况一直持续下去,一天中的每个小时都有一个新的 [LINETYPE]S。

现在,我想要实现的是为每个小时创建一个数组 - 每个值都包含另一个数组,其中括号作为键:

array("00:00:00" => array(

          array("LINETYPE" => "M",
          "TITLE" => "There For You",
          "PERFORMER" => "Martin Garrix & Troye Sivan",
          "MUSICID" => "21120",
          "LABEL" => ""),

           array("LINETYPE" => "M",
          "TITLE" => "Shut Up And Dance",
          "PERFORMER" => "Walk The Moon",
          "MUSICID" => "20634",
          "LABEL" => "")
   ), "01:00:00" => array(
   [...]
);

每小时搜索的正则表达式应该是正确的,但似乎 preg_split 不支持多个捕获组。

到目前为止,我发现的所有答案都处于更基本的水平,例如爆炸逗号。

这是我目前的代码。

$test = get_musiclog("06082017");

$hours = array();

$regex = "(\[LINETYPE\]S\t\[STARTTIME\])((?:(?:[0-2][0-9])|(?:[2][0-3])|(?:[0-9])):(?:[0-5][0-9])(?::[0-5][0-9])?(?:\\s?)?)\n";

if (preg_match_all ("/".$regex."/is", $test, $matches)) {
    foreach($matches[2] as $hour) {
        $hours[$hour] = ""; // Music array
    }
}

在想着这些问题挠头之后,几乎没有留下任何头发。谁能指出我正确的方向?

  • 如何将字符串与“[LINETYPE]S [STARTTIME]XX:XX:XX”分开并保持时间为键?
  • 知道结构是 [key]value\t 并且 \n 是分隔符,我如何拆分其余元素?
  • “数组中的数组中的数组”是正确的做法吗?

【问题讨论】:

  • 不要构建匹配所有的模式,使用 stream_get_line 以字符串[LINETYPE]S(例如)作为第三个参数逐块读取文件。
  • 不确定"LINETYPE" => "M"是否是要保留的相关信息,似乎与文件格式本身有关。

标签: php arrays regex


【解决方案1】:

我的方法主要使用否定字符类来捕获标签之间的值。为了保持 regex 模式相对较轻,使用了可选的捕获组,以便像 LINETYPE S 这样的短行仍然匹配。

代码:(Pattern Demo) (PHP Demo)

$input='[LINETYPE]S [STARTTIME]00:00:00
[LINETYPE]M [TITLE]There For You    [PERFORMER]Martin Garrix & Troye Sivan  [MUSICID]21120  [LABEL]     
[LINETYPE]M [TITLE]Shut Up and Dance    [PERFORMER]Walk The Moon    [MUSICID]20634  [LABEL] 
[LINETYPE]M [TITLE]Subeme La Radio  [PERFORMER]Enrique Iglesias [MUSICID]21105  [LABEL]     
[LINETYPE]C [TITLE]AUTO S2 NON STOP [PERFORMER] [MUSICID]A2-6   [LABEL]     
[LINETYPE]M [TITLE]Uptown Funk  [PERFORMER]Mark Ronson & Bruno Mars [MUSICID]20533  [LABEL]     
[LINETYPE]M [TITLE]Let It Go    [PERFORMER]James Bay    [MUSICID]20839  [LABEL]     
[LINETYPE]S [STARTTIME]01:00:00
[LINETYPE]M [TITLE]There For You    [PERFORMER]Martin Garrix & Troye Sivan  [MUSICID]21120  [LABEL]     
[LINETYPE]M [TITLE]Shut Up and Dance    [PERFORMER]Walk The Moon    [MUSICID]20634  [LABEL]     ';
$pattern='/\[LINETYPE\]([A-Z])\s\[(?:TITLE|STARTTIME)\]([^[\s]*(?: [^[\s]+)*)(?:\s*\[PERFORMER\]([^[ ]*(?: [^[ ]+)*)\s+\[MUSICID\]([^[ ]+)\s+\[LABEL\](\S*(?: \S+)*))?/';
if(!preg_match_all($pattern,$input,$out, PREG_SET_ORDER)){
    echo 'something went wrong';
}else{
    foreach($out as $a){
        if($a[1]=='S'){
            $time=$a[2];
        }else{
            $result[$time][]=["LINETYPE"=>$a[1],"TITLE"=>$a[2],"PERFORMER"=>$a[3],"MUSICID"=>$a[4],"LABEL"=>$a[5]];
        }
    }
}
var_export($result);

输出:

array (
  '00:00:00' => 
  array (
    0 => 
    array (
      'LINETYPE' => 'M',
      'TITLE' => 'There For You',
      'PERFORMER' => 'Martin Garrix & Troye Sivan',
      'MUSICID' => '21120',
      'LABEL' => '',
    ),
    1 => 
    array (
      'LINETYPE' => 'M',
      'TITLE' => 'Shut Up and Dance',
      'PERFORMER' => 'Walk The Moon',
      'MUSICID' => '20634',
      'LABEL' => '',
    ),
    2 => 
    array (
      'LINETYPE' => 'M',
      'TITLE' => 'Subeme La Radio',
      'PERFORMER' => 'Enrique Iglesias',
      'MUSICID' => '21105',
      'LABEL' => '',
    ),
    3 => 
    array (
      'LINETYPE' => 'C',
      'TITLE' => 'AUTO S2 NON STOP',
      'PERFORMER' => '',
      'MUSICID' => 'A2-6',
      'LABEL' => '',
    ),
    4 => 
    array (
      'LINETYPE' => 'M',
      'TITLE' => 'Uptown Funk',
      'PERFORMER' => 'Mark Ronson & Bruno Mars',
      'MUSICID' => '20533',
      'LABEL' => '',
    ),
    5 => 
    array (
      'LINETYPE' => 'M',
      'TITLE' => 'Let It Go',
      'PERFORMER' => 'James Bay',
      'MUSICID' => '20839',
      'LABEL' => '',
    ),
  ),
  '01:00:00' => 
  array (
    0 => 
    array (
      'LINETYPE' => 'M',
      'TITLE' => 'There For You',
      'PERFORMER' => 'Martin Garrix & Troye Sivan',
      'MUSICID' => '21120',
      'LABEL' => '',
    ),
    1 => 
    array (
      'LINETYPE' => 'M',
      'TITLE' => 'Shut Up and Dance',
      'PERFORMER' => 'Walk The Moon',
      'MUSICID' => '20634',
      'LABEL' => '',
    ),
  ),
)

【讨论】:

  • 这对我有很大帮助,谢谢!我尝试运行整个日志,发现如果没有设置 PERFORMER,则数组会发生一些奇怪的事情,并且会引发一些“未定义的偏移量”错误。第 6 行的示例here
  • 抱歉,我的原始帖子格式错误。每个条目都在不同的行上。
  • 我已经为它提供了所有可能的日志输出,它就像一个魅力!谢谢!
猜你喜欢
  • 1970-01-01
  • 2023-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多