PHP разделил строку с разделителями на пары ключ / значение (ассоциативный массив)
у меня есть такая строка:
key1value1key2value2key3value3key4value4key5value5
и я хотел бы, чтобы это был ассоциативный массив, чтобы я мог сделать:
echo $myArray['key1']; // prints value1
echo $myArray['key3']; // prints value3
//etc...
Я знаю, что могу взорваться на обратной косой черте, но не уверен, как идти оттуда.
3 ответов
использовать простой regex via preg_match_all
и array_combine
часто самый короткий и самый быстрый вариант:
preg_match_all("/([^\\]+)\\([^\\]+)/", $string, $p);
$array = array_combine($p[1], $p[2]);
теперь это, конечно, особый случай. Оба!--46-->ключи и значения разделены\ обратная косая черта, как и все пары из них. Регулярное выражение также немного длиннее из-за необходимого двойного экранирования.
однако эта схема может быть обобщена на другие key:value,
строк в стиле.
Distinct key:value,
разделители
общие варианты включают : и = как разделители ключа / значения, и , или & и другие в качестве разделителей пар. Регулярное выражение становится довольно очевидным в таких случаях (с /x
флаг для удобства чтения):
# ↓ ↓ ↓
preg_match_all("/ ([^:]+) : ([^,]+) /x", $string, $p);
$array = array_combine($p[1], $p[2]);
что делает его очень легко обмениваться :
и ,
для других разделителей.
- знаки равенства
=
вместо:
двоеточие. - классический
&
или;
как разделитель между парами ключ=значение. - или просто
\s
пробелы или\n
даже новые линии.
\t
как разделитель пар (разделенный вкладками ключ: списки значений)
разрешить различные разделители
вы можете сделать его более гибким / прощающим, разрешив различные разделители между ключи/значения/пары:
# ↓ ↓ ↓
preg_match_all("/ ([^:=]+) [:=]+ ([^,+&]+) /x", $string, $p);
когда как key=value,key2:value2++key3==value3
будет работать. Что может иметь смысл для более дружественных людей (он же нетехнические пользователи).
ограничить буквенно-цифровые клавиши
часто вы можете запретить что-либо, кроме классического key
идентификаторы. Просто используйте \w+
word string pattern, чтобы регулярное выражение пропускало нежелательные события:
# ↓ ↓ ↓
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.
альтернатива: 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=value&", $input_lines), $output);