试图在php中使字符串输出成为一个数组

时间:2016-02-08 18:52:00

标签: php

我遇到了一个问题,我从服务器上的RCON脚本得到一个相当不规则的字符串输出。当我在服务器上发送返回玩家的命令时,我得到一个如下所示的字符串:

rcon->get_players();

Players on server: [#] [IP Address]:[Port] [Ping] [GUID] [Name] -------------------------------------------------- 0 1.1.1.1:2 46 654321(OK) Player Name1 1 2.2.2.2:2 47 123456(OK) Player Name2 (2 players in total)

如果有帮助,这就是格式化的内容:

Players on server: 
[#] [IP Address]:[Port] [Ping] [GUID] [Name] 
-------------------------------------------------- 
0 1.1.1.1:2 46 654321(OK) Player Name1 
1 2.2.2.2:2 47 123456(OK) Player Name2 
(2 players in total)

所以第一个0是他们在服务器上的密钥ID(0-但是很多玩家),第二个是他们的IP和PORT,47是ping,playerguid是他们的战斗指导,然后是他们在游戏中的名字,然后共有球员回归。

然而,它作为一个大字符串返回。我正在试图找出如何将其提供给数组。所以我得到这样的东西:

array("id"=>"0", "Connection"=>"1.1.1.1:2", "ping"=>"46", "guid"=>"654321", "name"=>"Player Name1");

考虑到输出的不规则性,我能以任何方式实现这一目标吗?在字符串中包含标题会让我失望。

我遵循了Do not Panic的建议并且它已经接近了:UPDATED

echo "Player List:<br />";
$raw_players = $rcon->get_players();
$lines = explode("\n", $raw_players);
$end = count($lines)-1;
$keys = array('id','connection','ping','guid','name');
$regex = '/(\d+)\s+([\d\.\:]+)\s+(\d+)\s+(\d+)\(OK\)\s+(.+)/';
for ($i=3; $i < $end; $i++) {
    echo($lines[$i]);
    preg_match($regex, $lines[$i], $matches);
    unset($matches[0]);
    echo(var_dump($matches));
    $players[] = array_combine($keys, $matches);
}

我得到了:

Player List:
0 98.193.210.251:2304 47 e0b29e3c7122bda33b5391c22594c776(OK) Colin Fox
array (size=0)
  empty

3 个答案:

答案 0 :(得分:1)

首先,基于换行符进行爆炸以获取每行的数组。

$lines = explode("\n", $string);

然后你可以像这样构建一个不包括页眉和页脚的for循环:

$end = count($lines) - 1; // this will exclude the last line
for ($i=3; $i < $end; $i++) { // this will start at the fourth line

在循环内部,你可以再次使用exploed,以空格作为分隔符,为每一行获取一个数组。

$players[] = explode(' ', $lines[$i], 5);

这应该有效,因为看起来每行开头的所有值都没有空格。第三个参数(5)将阻止玩家名称在空间上分割(如果它包含空格),因为它将explode生成的数组的大小限制为5个元素。

如果希望结果数组具有字符串键,则可以定义键数组(在循环之前):

$keys = array('id', 'connection', 'ping', 'guid', 'name');

然后在循环中使用array_combine创建每个播放器数组。

$players[] = array_combine($keys, explode(' ', $lines[$i], 5));

有了这个字符串的一些新信息,似乎有些列被多个空格(而不是相同数量的空格)分隔,因此爆炸不适用于此。您可以在循环中使用正则表达式匹配。

$keys = array('id', 'connection', 'ping', 'guid', 'name');
$regex = '/(\d+)\s+([\d\.\:]+)\s+(\d+)\s+(\w+)\(OK\)\s+(.+)/';
for ($i=3; $i < $end; $i++) {
    preg_match($regex, $lines[$i], $matches);
    unset($matches[0]);
    $players[] = array_combine($keys, $matches);
}

unset($matches[0]);是因为preg_match匹配中的第一个元素将是整个字符串。 $matches中的每个后续值都将是捕获组的内容。以下是正则表达式的解释:

/            begin pattern
(\d+)        capture one or more digits (id)
\s+          skip one or more spaces
([\d\.\:]+)  capture one or more characters either digit, dot, or colon (ip/port)
\s+          skip one or more spaces
(\d+)        capture one or more digits (ping)
\s+          skip one or more spaces
(\w+)        capture one or more alphanumeric characters (guid)
\(OK\)\s+    skip the (OK) and one or more spaces
(.+)         capture everything else (player name)
/            end pattern

答案 1 :(得分:0)

您可以使用空格作为分隔符轻松地在字符串上使用explode()函数。从那里只使用数组的后半部分。

或者使用explode(),但设置一个限制,以便可以将数组中的最后一个元素分解为第二个数组。

答案 2 :(得分:0)

我会在其上使用正则表达式,如下所示:

(\d+) ([\d.:]+) (\d+) (\d+)\([^)]+\) (.*)

与PHP中的preg_match_all相结合:

preg_match_all('#(\d+) ([\d.:]+) (\d+) (\d+)\([^)]+\) (.*)#', $players, $matches);