Разделение разделителя строк в PHP на пары ключей / значений (ассоциативный массив)

У меня есть строка вроде этого:

key1\value1\key2\value2\key3\value3\key4\value4\key5\value5 

И я бы хотел, чтобы это был ассоциативный массив, чтобы я мог:

 echo $myArray['key1']; // prints value1 echo $myArray['key3']; // prints value3 //etc... 

Я знаю, что могу взорваться на обратной косой чертой, но не знаю, как идти оттуда.

Related of "Разделение разделителя строк в PHP на пары ключей / значений (ассоциативный массив)"

Использование простого регулярного выражения через 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 качестве разделителя пары (перечни разделов с табуляцией: значения)
  • Classic & 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-стиля

И вы можете создать базовый метод извлечения 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', ...
  • и, затем, итерации по этому списку с скачком 2, используя каждый раз:
    • один элемент в качестве ключа – тот, на который указывает $i
    • тот, который сразу после него, как значение – тот, на который указывает $i+1

Я не так хорош с RegExp, но как насчет этого одного кода строки

 parse_str(preg_replace("/key(.*?)\\value(.*?)(\\|$)/", "key$1=value$2&", $input_lines), $output);