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

报告相同问题?

悬赏问题

  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥15 stable diffusion
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条