2009-10-22 6 views
3

d'une chaîne avec des paires attribut/valeur tels queParse une liste d'attributs/valeurs en PHP

attr1="some text" attr2 = "some other text" attr3= "some weird [email protected]'#$\"=+ text" 

le but est d'analyser et de sortie d'un tableau associatif, dans ce cas:

array('attr1' => 'some text', 
     'attr2' => 'some other text', 
     'attr3' => 'some weird [email protected]\'#$\"=+ text') 

Notez l'espacement incohérent autour des signes égal, le guillemet double échappé dans l'entrée et le guillemet simple échappé dans la sortie.

+2

Vous n'êtes pas l'analyse d'un langage de balisage, droite? –

+0

Bon à demander! Non, juste ma propre syntaxe pour être facile à taper sur une ligne de commande. – dreeves

+2

"être facile à taper sur une ligne de commande", alors vous pourriez être intéressé par http://docs.php.net/getopt – VolkerK

Répondre

6

Essayez quelque chose comme ceci:

$text = "attr1=\"some text\" attr2 = \"some other text\" attr3= \"some weird [email protected]'#$\\\"=+ text\""; 
echo $text; 
preg_match_all('/(\S+)\s*=\s*"((?:\\\\.|[^\\"])*)"/', $text, $matches, PREG_SET_ORDER); 
print_r($matches); 

qui produit:

attr1="some text" attr2 = "some other text" attr3= "some weird [email protected]'#$\"=+ text" 

Array 
(
    [0] => Array 
     (
      [0] => attr1="some text" 
      [1] => attr1 
      [2] => some text 
     ) 

    [1] => Array 
     (
      [0] => attr2 = "some other text" 
      [1] => attr2 
      [2] => some other text 
     ) 

    [2] => Array 
     (
      [0] => attr3= "some weird [email protected]'#$\"=+ text" 
      [1] => attr3 
      [2] => some weird [email protected]'#$\"=+ text 
     ) 

) 

Et une brève explication:

(\S+)    // match one or more characters other than white space characters 
        // > and store it in group 1 
\s*=\s*    // match a '=' surrounded by zero or more white space characters 
"     // match a double quote 
(     // open group 2 
    (?:\\\\.|[^\\"])* // match zero or more sub strings that are either a backslash 
        // > followed by any character, or any character other than a 
        // > backslash 
)     // close group 2 
"     // match a double quote 
+0

Qu'en est-il du troisième exemple? – Gumbo

+0

Oui, j'ai oublié de double échapper le backslash (et double vérifier la sortie). J'ai peur d'avoir parfois trop confiance en moi. Merci. –

+0

Y at-il une différence entre la façon dont php et actionscript, c'est ecmascript/js btw, gère regex? Parce que cette regex n'a donné que les deux premiers attrs dans actionscript. – Amarghosh

2

EDIT: Ce regex échoue si la valeur se termine par une barre oblique inverse comme attr4="something\\"

Je ne sais pas PHP, mais l'expression rationnelle serait essentiellement le même dans toutes les langues, c'est ainsi que je l'ai fait dans ActionScript:

var text:String = "attr1=\"some text\" attr2 = \"some other text\" attr3= \"some weird [email protected]'#$\\\"=+ text\""; 

var regex:RegExp = /\s*(\w+)\s*=\s*(?:"(.*?)(?<!\\)")\s*/g; 

var result:Object; 
while(result = regex.exec(text)) 
    trace(result[1] + " is " + result[2]); 

Et je suis arrivé ce qui suit eteint:

attr1 est un texte
attr2 est un autre texte
attr3 est un peu bizarre! @ '# $ \ "= + texte

+0

Juste un petit pointeur: si la valeur contient une barre oblique inverse elle-même, comme 'attr3 =" \\ "' (qui devra probablement s'échapper aussi), cela ne fonctionnera pas avec un négatif regarde derrière, bien sûr, cela ne se produira peut-être jamais, l'OP n'a pas mentionné de tels cas d'angle –

+0

Oui tu as raison. Et ce n'est pas un nitpick - apparemment, cela échoue si la chaîne se termine par un backslash - comme 'attr4 =" quelque chose \\ "' – Amarghosh