PHP divise la chaîne délimitée en paires clé / valeur (tableau associatif))
j'ai une chaîne comme celle-ci:
key1value1key2value2key3value3key4value4key5value5
et j'aimerais que ce soit un tableau associatif pour que je puisse faire:
echo $myArray['key1']; // prints value1
echo $myArray['key3']; // prints value3
//etc...
je sais que je peux exploser sur le revers, mais je ne sais pas comment partir de là.
3 réponses
utilisant un simple regex via preg_match_all
et array_combine
est souvent l'option la plus courte et la plus rapide:
preg_match_all("/([^\\]+)\\([^\\]+)/", $string, $p);
$array = array_combine($p[1], $p[2]);
ceci est bien sûr un cas particulier. Les deux clés et valeurs sont séparés par un \ antislash, comme le sont toutes les paires d'entre eux. L'expression régulière est également un peu plus long en raison de la nécessaire double évasion.
cependant ce schéma peut être généralisé à d'autres chaînes de style key:value,
.
Distinct key:value,
séparateurs
les variations courantes incluent : et = comme séparateurs clé/valeur, et , ou et et d'autres comme délimiteurs de paires. Le regex devient assez évident dans de tels cas (avec le /x
indicateur de lisibilité):
# ↓ ↓ ↓
preg_match_all("/ ([^:]+) : ([^,]+) /x", $string, $p);
$array = array_combine($p[1], $p[2]);
, ce Qui rend très facile l'échange :
et ,
pour d'autres délimiteurs.
- signe " Égal
=
au lieu de:
deux-points. - par exemple
\t
comme délimiteur de paires (tab-clé séparée:listes de valeurs) - Classique
&
ou;
comme séparateur entre des paires valeur / clé. - ou juste
\s
espaces ou\n
newlines Pair.
autoriser des délimiteurs variables
vous pouvez le rendre plus flexible / indulgente en permettant différents délimiteurs entre clés/valeurs/ paires:
# ↓ ↓ ↓
preg_match_all("/ ([^:=]+) [:=]+ ([^,+&]+) /x", $string, $p);
où les deux key=value,key2:value2++key3==value3
fonctionneraient. Ce qui peut avoir du sens pour plus d'human-friendlinies (alias non-technical users).
limite alphanumérique clés
souvent, vous pouvez vouloir interdire tout sauf les identificateurs classiques key
. Il suffit d'utiliser un motif de chaîne de mots \w+
pour faire passer le regex sur les occurences indésirables:
# ↓ ↓ ↓
preg_match_all("/ (\w+) = ([^,]+) /x", $string, $p);
c'est l'approche la plus triviale. Si OTOH vous voulez affirmer / contraindre toute la clé / chaîne de valeur à l'avance, puis d'élaborer une preg_match("/^(\w+=[^,]+(,|$))+/", …
la Bande des espaces ou des citant
vous pouvez sauter quelques étapes post-traitement (comme trim
sur les clés et les valeurs) avec un petit ajout:
preg_match_all("/ \s*([^=]+) \s*=\s* ([^,]+) (?<!\s) /x", $string, $p);
ou par exemple des citations facultatives:
preg_match_all("/ \s*([^=]+) \s*=\s* '? ([^,]+) (?<![\s']) /x", $string, $p);
extraction de style INI
et vous pouvez élaborer une méthode D'extraction de fichier INI de base:
preg_match_all("/^ \s*(\w+) \s*=\s* ['\"]?(.+?)['\"]? \s* $/xm", $string, $p);
veuillez noter que ce n'est qu'un brut sous-ensemble des régimes INI communs.
Alternative: parse_str()
si vous avez déjà une chaîne de caractères key=value&key2=value2
, alors parse_str
fonctionne comme un charme. Mais en le combinant avec strtr
peut même traiter d'autres délimiteurs variables:
# ↓↓ ↑↑
parse_str(strtr($string, ":,", "=&"), $pairs);
qui a un couple de pour et contre de le sien:
- encore plus courte que l'approche regex à deux lignes.
- Prédéfine un mécanisme d'échappement bien connu, tel que
%2F
pour les caractères spéciaux). - ne permet pas de faire varier les délimiteurs, ou les délimiteurs non délimités à l'intérieur.
- convertit automatiquement
keys[]=
en tableaux, que vous pouvez ou non vouloir cependant.
Alternative: explode
+ foreach
vous trouverez de nombreux exemples de clé manuelle/extension de chaîne de valeur . Bien que ce soit souvent plus de code. explode
est quelque peu surutilisé dans PHP en raison d'hypothèses d'optimisation. Après le profilage s'avère souvent être plus lent cependant en raison de la manuel foreach
et la collection de tableaux.
Que penser de quelque chose comme ceci :
$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);
Qui serait que vous obtenez :
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)
Fondamentalement, ici, l'idée est de:
- fractionner la chaîne
- qui vous donnera un tableau tel que
'key1', 'value1', 'key2', 'value2', ...
- et, ensuite, itérez sur cette liste, avec un saut de 2, en utilisant chaque fois :
- un élément la clé -- celle pointée par
$i
- celui juste après lui comme la valeur -- celui pointé par
$i+1
- un élément la clé -- celle pointée par
Je ne suis pas si bon avec RegExp mais que dire de ce code de ligne
parse_str(preg_replace("/key(.*?)\value(.*?)(\|$)/", "key=value&", $input_lines), $output);