将字符串转换为key =>价值对

时间:2014-11-27 21:43:21

标签: php string

我有以下字符串:

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;   
            }
        }

    }
}

并且Output就像这个带有数字索引的数组: 但这实际上并不是我所需要的。

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"
  )
)

5 个答案:

答案 0 :(得分:1)

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

$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];
    }    
}

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

答案 1 :(得分:0)

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

这是实施:

<?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);
?>

度过美好的一天

答案 2 :(得分:0)

只使用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
        )
)

答案 3 :(得分:0)

设定:

<?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);

答案 4 :(得分:0)

有很多方法可以解析这些数据。我觉得最简单的方法就是为它写一个正则表达式。

$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);

Regex explanation

结果

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
        )
)