У меня есть строка вроде этого:
key1\value1\key2\value2\key3\value3\key4\value4\key5\value5
И я бы хотел, чтобы это был ассоциативный массив, чтобы я мог:
echo $myArray['key1']; // prints value1 echo $myArray['key3']; // prints value3 //etc...
Я знаю, что могу взорваться на обратной косой чертой, но не знаю, как идти оттуда.
Использование простого регулярного выражения через preg_match_all
и array_combine
часто является самым коротким и быстрым вариантом:
preg_match_all("/([^\\\\]+)\\\\([^\\\\]+)/", $string, $p); $array = array_combine($p[1], $p[2]);
Теперь это, конечно, особый случай. Оба ключа и значения разделяются символом \ backslash, как и все пары из них. Регулярное выражение также немного длиннее из-за необходимого двойного экранирования.
Однако эта схема может быть обобщена на другие key:value,
строки key:value,
-style.
key:value,
разделители Общие вариации включают : и = как разделители ключей / значений, и , или & или другие, как пары разделителей. Регулярное выражение становится довольно очевидным в таких случаях (с флагом /x
для удобочитаемости):
# ↓ ↓ ↓ preg_match_all("/ ([^:]+) : ([^,]+) /x", $string, $p); $array = array_combine($p[1], $p[2]);
Это делает его очень простым для обмена :
и для других разделителей.
=
вместо :
двоеточия. \\t
качестве разделителя пары (перечни разделов с табуляцией: значения) &
or ;
как разделитель между парами ключ = значение. \\s
пробелы или \\n
новых строк. Вы можете сделать его более гибким / прощающим, разрешив разные разделители между ключами / значениями / парами:
# ↓ ↓ ↓ preg_match_all("/ ([^:=]+) [:=]+ ([^,+&]+) /x", $string, $p);
Если оба key=value,key2:value2++key3==value3
будет работать. Что может иметь смысл для большего количества человеческих друзей (нетехнических пользователей AKA).
Зачастую вы можете запретить что-либо, кроме классических идентификаторов key
. Просто используйте шаблон строки \w+
, чтобы заставить регулярное выражение пропускать нежелательные события:
# ↓ ↓ ↓ preg_match_all("/ (\w+) = ([^,]+) /x", $string, $p);
Это самый тривиальный подход в отношении белых списков. Если OTOH вы хотите заранее указать / ограничить всю строку ключа / значения, тогда создайте отдельный preg_match("/^(\w+=[^,]+(,|$))+/", …
Вы можете пропустить несколько этапов последующей обработки (например, trim
клавиши и значения) с небольшим добавлением:
preg_match_all("/ \s*([^=]+) \s*=\s* ([^,]+) (?<!\s) /x", $string, $p);
Или, например, необязательные кавычки:
preg_match_all("/ \s*([^=]+) \s*=\s* '? ([^,]+) (?<![\s']) /x", $string, $p);
И вы можете создать базовый метод извлечения INI-файла:
preg_match_all("/^ \s*(\w+) \s*=\s* ['\"]?(.+?)['\"]? \s* $/xm", $string, $p);
Обратите внимание, что это всего лишь грубое подмножество общих схем ИНИ.
parse_str()
Если у вас уже есть строка key=value&key2=value2
, то parse_str
работает как шарм. Но, объединив его с strtr
можно даже обрабатывать различные другие разделители:
# ↓↓ ↑↑ parse_str(strtr($string, ":,", "=&"), $pairs);
У которого есть несколько плюсов и минусов :
%2F
для специальных символов). keys[]=
в массивы, которые вы можете или не хотите. explode
+ foreach
Вы найдете много примеров расширения ручного ключа / значения строки . Хотя это часто больше кода. explode
несколько запутан в PHP из-за оптимизационных предположений. После профилирования часто оказывается медленнее, однако из-за ручной коллекции foreach
и массива.
Что-то вроде этого:
$str = 'key1\value1\key2\value2\key3\value3\key4\value4\key5\value5'; $list = explode('\\', $str); $result = array(); for ($i=0 ; $i<count($list) ; $i+=2) { $result[ $list[$i] ] = $list[$i+1]; } var_dump($result);
Который доставит вас:
array 'key1' => string 'value1' (length=6) 'key2' => string 'value2' (length=6) 'key3' => string 'value3' (length=6) 'key4' => string 'value4' (length=6) 'key5' => string 'value5' (length=6)
В принципе, здесь идея заключается в следующем:
'key1', 'value1', 'key2', 'value2', ...
$i
$i+1
Я не так хорош с RegExp, но как насчет этого одного кода строки
parse_str(preg_replace("/key(.*?)\\value(.*?)(\\|$)/", "key$1=value$2&", $input_lines), $output);