Используя простое регулярное выражение через preg_match_all
и array_combine
часто являются самым коротким и быстрым вариантом:
preg_match_all("/([^\\\\]+)\\\\([^\\\\]+)/", $string, $p);
$array = array_combine($p[1], $p[2]);
Теперь это, конечно, частный случай. И ключи, и значения разделяются обратной косой чертой \, как и все их пары. Регулярное выражение также немного длиннее из-за необходимости двойного экранирования.
Однако эту схему можно обобщить и на другие строки в стиле key:value,
.
Отдельные key:value,
разделители
Общие варианты включают : и = в качестве разделителей ключ/значение и , или & и другие в качестве разделителей пар. В таких случаях регулярное выражение становится довольно очевидным (с флагом /x
для удобства чтения):
# ↓ ↓ ↓
preg_match_all("/ ([^:]+) : ([^,]+) /x", $string, $p);
$array = array_combine($p[1], $p[2]);
Это позволяет очень легко заменить :
и ,
на другие разделители.
- Знаки равенства
=
вместо :
двоеточий.
- Например,
\\t
в качестве разделителя пар (списки ключ:значение, разделенные табуляцией)
- Классический
&
или ;
в качестве разделителя между парами ключ=значение.
- Или просто
\\s
пробелов или даже \\n
новых строк.
Разрешить различные разделители
Вы можете сделать его более гибким/прощающим, разрешив разные разделители между ключами/значениями/парами:
# ↓ ↓ ↓
preg_match_all("/ ([^:=]+) [:=]+ ([^,+&]+) /x", $string, $p);
Где оба key=value,key2:value2++key3==value3
будут работать. Что может иметь смысл для более дружественных людей (также известных как нетехнические пользователи).
Ограничение буквенно-цифровых клавиш
Часто вам может понадобиться запретить что-либо, кроме классических идентификаторов 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);
Обратите внимание, что это всего лишь грубое подмножество общих схем INI.
Если у вас уже есть строка key=value&key2=value2
, то parse_str
отлично работает. Но, комбинируя его с strtr
, можно даже обрабатывать различные другие разделители:
# ↓↓ ↑↑
parse_str(strtr($string, ":,", "=&"), $pairs);
Что имеет несколько собственных за и против:
- Даже короче, чем подход с двухстрочным регулярным выражением.
- Предопределяет хорошо известный механизм экранирования, такой как
%2F
для специальных символов).
- Не допускает изменения разделителей или неэкранированных разделителей внутри.
- Автоматически преобразует
keys[]=
в массивы, которые вам могут понадобиться, а могут и не понадобиться.
Альтернатива: explode
+ foreach
Вы найдете много примеров расширения строки ключ/значение вручную. Хотя это часто больше кода. explode
несколько злоупотребляют в PHP из-за предположений об оптимизации. Однако профилирование часто оказывается медленнее из-за ручного foreach
и сбора массива.
person
mario
schedule
13.03.2011