douyuqing_12345 2016-02-08 18:51
浏览 67
已采纳

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

I'm running into an issue where I get a rather irregular string output from an RCON script on a server. When I send a command for returning players on a server, I get a string that looks like this:

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)

Here's what it looks like formatted if that helps:

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)

So the first 0 is their key id on the server (0-however many players), the second is their IP and PORT, the 47 is the ping, playerguid is their battleye guid, then their name inthe game, and then a total of the players returned.

However, it returns as one big string. I'm trying to figure out how to feed this into an array. So I get something like this:

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

Any way I can achieve this, considering how irregular the output is? Having the headers in the string is throwing me off.

I followed Don't Panic's advice and it's close: UPDATED

echo "Player List:<br />";
$raw_players = $rcon->get_players();
$lines = explode("
", $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);
}

And I get:

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

3条回答 默认 最新

  • douke9379 2016-02-08 20:03
    关注

    First, explode based on newlines to get an array of each line.

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

    then you can construct a for loop excluding the header and footer like this:

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

    inside the loop, you can use explode again, with space as the delimiter, to get an array for every line.

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

    This should work, because it looks like all the values at the beginning of each line do not have spaces. The third argument (5) will prevent the player name from being split on space (if it contains a space) because it restricts the size of the array generated by explode to 5 elements.

    If you want the resulting array to have string keys, you can define an array of keys (before your loop):

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

    And then use array_combine in your loop to create each player array.

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

    With some new info about this string, it seems that some of the columns are separated by more than one space (and not the same number of spaces), so explode will not work for this. You can use a regular expression match in your loop instead.

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

    The unset($matches[0]); is because the first element in the preg_match matches will be the entire string. Each of the subsequent values in $matches will be the contents of the capture groups. Here is an explanation of the regex:

    /            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
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥50 永磁型步进电机PID算法
  • ¥15 sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?
  • ¥88 找成都本地经验丰富懂小程序开发的技术大咖
  • ¥15 如何处理复杂数据表格的除法运算
  • ¥15 如何用stc8h1k08的片子做485数据透传的功能?(关键词-串口)
  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥200 uniapp长期运行卡死问题解决
  • ¥15 latex怎么处理论文引理引用参考文献
  • ¥15 请教:如何用postman调用本地虚拟机区块链接上的合约?
  • ¥15 为什么使用javacv转封装rtsp为rtmp时出现如下问题:[h264 @ 000000004faf7500]no frame?