2016-02-08 2 views
0

У меня возникла проблема, когда я получаю довольно нерегулярный вывод строки из сценария RCON на сервере. Когда я посылаю команду для возвращения игроков на сервере, я получаю строку, которая выглядит следующим образом:Попытка сделать строку вывести массив в php

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 их ключевой идентификатор на сервере (0-но много игроков), второй - их IP и PORT, 47 - пинг, playerguid - их баттли-гид, затем их имя в игре, а затем общее количество игроков возвращается.

Однако он возвращается как одна большая строка. Я пытаюсь понять, как передать это в массив. Поэтому я получаю что-то вроде этого:

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

Любой способ добиться этого, учитывая, насколько нерегулярным является выход? Наличие заголовков в строке отбрасывает меня.

Я последовал Не паникуйте то совету, и это близко: ОБНОВЛЕНО

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 
+0

Не могли бы вы предоставить более длинный отрывок из реальных данных? Просто замените ip-адреса и имена пользователей. Эта строка не очень полезна. – migg

+0

, что одна строка - это два игрока, которые подключены, если бы я добавил больше, он бы выглядел так: «1 1.1.1.1: 46 654321 (OK)« Имя игрока3 »и продолжайте повторять так. – Flynn

+0

Я отформатировал таблицу, если это помогает, она выводится как строка runnon, но я добавил разрывы строк, чтобы было легче увидеть, что он пишет – Flynn

ответ

1

Во-первых, взрываются на основе новых строк, чтобы получить массив каждой строки.

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

, то вы можете построить цикл, исключая верхний и нижний колонтитулы, как это:

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

внутри цикла, вы можете использовать взорваться снова, с пространством в качестве разделителя, чтобы получить массив для каждая линия.

$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 
+0

На правильном пути я добавил, что произошло наверху. – Flynn

+0

Моя проблема: я не получаю регулярное выражение, и я никогда не смогу понять, как использовать глупые вещи. Как я использую регулярное выражение для трех пробелов и «(OK)» – Flynn

+0

по каким-то причинам совпадения отображаются пустым. – Flynn

0

Вы можете легко использовать функцию explode() на строку, используя пробелы в качестве разделителей. Отсюда просто используйте только вторую половину массива.

В качестве альтернативы можно использовать explode(), но установить предел таким образом, чтобы конечный элемент в массиве затем мог быть разбит на второй массив.

+0

Итак, вы говорите, что используете взрыв и отслеживаете, сколько утерянных значений массива есть и всегда начинаются с начала списка после потерянных значений? Потому что другая часть состоит в том, что мне нужно будет избавиться от заявления (всего бла-игроков) в конце тоже. – Flynn

+0

Если формат выходной строки всегда один и тот же, как только вы запустите его и распечатаете вывод за один раз, вы сможете узнать, какие элементы имеют значение. – jstrieb

0

Я хотел бы использовать регулярное выражение, что, который выглядит следующим образом:

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

в сочетании с preg_match_all в PHP так:

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

Хорошо, извините, что? Я сосать с регулярными выражениями, не могли бы вы разбить этот стиль барни для меня? – Flynn

+0

Вы можете оформить заказ на https://regex101.com/. Регулярное выражение соответствует цифрам, затем цифрам, точкам и двоеточиям, затем цифрам, затем цифрам, за которыми следуют элементы внутри '()', затем остальная часть строки. – migg

Смежные вопросы