将字符串转换为键 => 值对


Convert string as key => value pairs

我有以下字符串:

Host                          dnsmgr   Username       Refresh State                Reg.Time
sip.voicetrading.com:5060     N        travelAsk        105 Registered           Thu, 27 Nov 2014 15:57:43
sip.alonia.es:5060            N        user431          225 Registered           Thu, 27 Nov 2014 23:28:24

我想以某种方式使这个字符串成为关联数组。

像这样:

array(
   'sip.voicetrading.com' => array (
       'port'   => 5060,
       'username' =>'travelAsk',
       'refresh'   => 105,
       'state'     => 'Registered',
       'time'      => 'Thu, 27 Nov 2014 15:57:43'
   ),
   'sip.alonia.es' => array (
       'port'   => 5060,
       'username' =>' user431',
       'refresh'   => 225,
       'state'     => 'Registered',
       'time'      => 'Thu, 27 Nov 2014 23:28:24'
   )
);

你能告诉我一种方法,这将是最好的方法吗?

到目前为止,我尝试了这样的事情:

$peer = array(
  "data"=>
"Host                                    dnsmgr Username       Refresh State                Reg.Time                 
sip.voicetrading.com:5060               N      travelIhome        105 Registered           Thu, 27 Nov 2014 16:39:45 " ;

foreach (explode("'n", $peer['data']) as $line) {
    $a = strpos('z' . $line, ':') - 1;
    if ($a >= 0) {
        $arrTrunkSettings = explode (' ', trim(substr($line, $a + 1)));
        foreach ($arrTrunkSettings as $key => $value) {
            if (!empty($value)) {
                $data[trim(substr($line, 0, $a))][] = $value;   
            }
        }
    }
}

输出就像这个带有数字索引的数组:但这实际上不是我需要的。

array (
  "sip.voicetrading.com" =>
  array(
    [0]=> "5060"
    [1]=> "N"
    [2]=> "travelAsk"
    [3]=> "105"
    [4]=> "Registered"
    [5]=> "Thu,"
    [6]=> "27"
    [7]=> "Nov"
    [8]=> "2014"
    [9]=> "16:32:45"
  )
)

编辑:缩短了解决方案。这与我的第一个答案相同,但现在代码只有一半。首先,它获取所有行,然后将标头拉取并拆分为一个单独的数组。然后,它可以循环其余行,并使用标题作为键将它们添加到结果中。

$result = array();
$lines = explode("'n", $string);
$headers = preg_split("/'s+/", array_shift($lines), 6);
foreach ($lines as $line) {
    $part = preg_split('/'s+/', $line, 6);
    $info = explode(":", $part[0]);
    $result[$info[0]]['port'] = $info[1];
    for($i = 1; $i < count($headers); $i++) {
        $result[$info[0]][$headers[$i]] = $part[$i];
    }    
}

这为您提供了一个与您要求的结果数组匹配的结果数组。它从标头中获取键/值对,因此如果输入发生变化,生成的数组也会发生变化,这与硬编码解决方案不同。

  • 您确实应该拆分新行的输入
  • 您应该消除不必要的空格
  • 然后,您应该将每一行拆分为一个空格,并将值存储在关联数组中的必要列中

这是实现:

<?php
$input = "Host                          dnsmgr   Username       Refresh State                Reg.Time
sip.voicetrading.com:5060     N        travelAsk        105 Registered           Thu, 27 Nov 2014 15:57:43
sip.alonia.es:5060            N        user431          225 Registered           Thu, 27 Nov 2014 23:28:24";
$rows = explode("'n", $input);
unset($rows[0]);
$objects = array();
foreach ($rows as $row)
{
    $object = array();
    echo $row . "'n";
    $row = preg_replace("/'' +/", " ", $row); //Reducing all whitespace into single spaces
    $index = strpos($row, " ");
    $addr = substr($row, 0, $index);
    $host = substr($addr, 0, strpos($addr, ":"));
    $port = str_replace($host.":", "", $addr);
    $row = substr($row, $index + 1, strlen($row));
    $index = strpos($row, " ");
    $mgr = substr($row, 0, $index);
    $row = substr($row, $index + 1, strlen($row));
    $index = strpos($row, " ");
    $user = substr($row, 0, $index);
    $row = substr($row, $index + 1, strlen($row));
    $index = strpos($row, " ");
    $refresh = substr($row, 0, $index);
    $row = substr($row, $index + 1, strlen($row));
    $index = strpos($row, " ");
    $state = substr($row, 0, $index);
    $row = substr($row, $index + 1, strlen($row));
    $object["port"] = $port;
    $object["dnsmgr"] = $mgr;
    $object["username"] = $user;
    $object["refresh"] = $refresh;
    $object["state"] = $state;
    $object["time"] = $row;
    $objects[$host] = $object;
}
print_r($objects);
?>

祝你今天开心

通过使用preg_split(),您可能会省去很多麻烦:

<?php
$peer = array( "data" =>
"Host                          dnsmgr   Username       Refresh State                Reg.Time
sip.voicetrading.com:5060     N        travelAsk        105 Registered           Thu, 27 Nov 2014 15:57:43
sip.alonia.es:5060            N        user431          225 Registered           Thu, 27 Nov 2014 23:28:24"
); 
$obj = array();
foreach( explode( "'n", $peer['data'] ) as $line ) {
  $v1 = preg_split( "/:/", trim( $line ), 2 );
  if( sizeof( $v1 ) == 2 ) {
    $v2 = preg_split( "/'s+/", $v1[1], 6 );
    $obj[$v1[0]] = array(
      "port"     => $v2[0],
      "username" => $v2[2],
      "refresh"  => $v2[3],
      "state"    => $v2[4],
      "time"     => $v2[5]
    );
  }
}
print_r( $obj );
?>

结果:

Array
(
    [sip.voicetrading.com] => Array
        (
            [port] => 5060
            [username] => travelAsk
            [refresh] => 105
            [state] => Registered
            [time] => Thu, 27 Nov 2014 15:57:43
        )
    [sip.alonia.es] => Array
        (
            [port] => 5060
            [username] => user431
            [refresh] => 225
            [state] => Registered
            [time] => Thu, 27 Nov 2014 23:28:24
        )
)

设置:

<?php
  $peer = array('data' =>
'Host                          dnsmgr   Username       Refresh State                Reg.Time
sip.voicetrading.com:5060     N        travelAsk        105 Registered           Thu, 27 Nov 2014 15:57:43
sip.alonia.es:5060            N        user431          225 Registered           Thu, 27 Nov 2014 23:28:24'
  );

首先,将原始数据拆分为行。从第一行中提取字段标签,然后删除此行。将第一个标签替换为 "Port"

  $lines = explode ("'n", $peer['data']);
  if (count ($lines)) {
    $line = array_shift ($lines);
    $labels = preg_split ('/''s+/', trim($line));
    $labels[0] = 'Port';
    $max_fields = count ($labels);
  }

现在循环访问剩余的行。将行拆分为字段,然后从第一个字段中提取主机和端口。将第一个字段替换为端口。然后使用array_combine()合并标签和数据。

请注意使用 $max_fields 以避免将Reg.Time拆分为多个字段。仅当Reg.Time是行中的最后一个字段时,此操作才有效。

  $data = array();
  foreach ($lines as $line) {
    $fields = preg_split ('/''s+/', trim($line), $max_fields);
    if (count ($fields) < $max_fields) {
      // Error
    }
    $hostport = explode (':', $fields[0], 2);
    $host = $hostport[0];
    $port = $hostport[1];
    $fields[0] = $port;
    $data[$host] = array_combine ($labels, $fields);
  }
  print_r ($data);
有很多

方法可以解析此数据。我觉得最简单的方法是为它写一个正则表达式。

$peerData = 'Host                          dnsmgr   Username       Refresh State                Reg.Time
         sip.voicetrading.com:5060     N        travelAsk        105 Registered           Thu, 27 Nov 2014 15:57:43
         sip.alonia.es:5060            N        user431          225 Registered           Thu, 27 Nov 2014 23:28:24';
// Split the string into lines
$lines = explode("'n", $peerData);
// Remove the header
unset($lines[0]);
// Loop over each line
$peers = [];
foreach ($lines as $line) {
    $matches = [];
    preg_match('/'s*(?P<hostname>['w'.]+):(?P<port>'d+)'s*(?P<dnsmgr>.)'s*(?P<username>'w+)'s*(?P<refresh>'d+)'s*(?P<state>'w+)'s*(?P<time>.+)/', $line, $matches);
    // Build the entry
    $peers[$matches['hostname']] = [
        'port'     => $matches['port'],
        'username' => $matches['username'],
        'refresh'  => $matches['refresh'],
        'state'    => $matches['state'],
        'time'     => $matches['time'],
    ];
}
print_r($peers);

正则表达式解释

结果

Array
(
    [sip.voicetrading.com] => Array
        (
            [port] => 5060
            [username] => travelAsk
            [refresh] => 105
            [state] => Registered
            [time] => Thu, 27 Nov 2014 15:57:43
        )
    [sip.alonia.es] => Array
        (
            [port] => 5060
            [username] => user431
            [refresh] => 225
            [state] => Registered
            [time] => Thu, 27 Nov 2014 23:28:24
        )
)