2009-12-01 3 views
2

J'essaie de faire correspondre des chaînes entre guillemets dans un morceau de texte et de permettre des citations échappées à l'intérieur de celui-ci. J'ai essayé cette expression régulière dans un testeur en ligne, et cela fonctionne parfaitement. Cependant, quand je l'essaie dans preg_match_all, il échoue à la première chaîne échappée.expression regex pour la chaîne entre guillemets échappée ne fonctionnera pas dans preg_match_all de php

Voici le code:

$parStr = 'title="My Little Website" 
    year="2007" 
    description="Basic website with ..." 
    tech="PHP, mySQL" 
    link="<a href=\"http://test.com\">test.com</a>" 
'; 
$matches = array(); 

preg_match_all('/(\w+)\s*=\s*"(([^\\"]*(\\.)?)*)"/', $parStr, $matches, PREG_SET_ORDER); // Match[4][0] is 'link="<a href=\"' 

Il échoue sur le dernier match, correspondant seulement jusqu'à la première citation échappé. Lorsque j'essaie cette expression au http://www.regexplanet.com/simple/index.html, cela fonctionne parfaitement.

La partie pertinente de l'expression rationnelle est

"(([^\\"]*(\\.)?)*)" 

qui devrait manger tout le texte menant à une citation échappé ou une citation, puis en mangeant un devis échappé en option, de ce procédé est répété 0 fois ou plus , jusqu'à ce qu'une citation non échappée soit trouvée, dans laquelle la correspondance est complète.

Pourquoi cela ne fonctionne-t-il pas en php? Pourquoi cela ne fonctionne-t-il pas et comment devrait-il être réparé?

+0

dans $ parStr, qu'essayez-vous de trouver? – ghostdog74

Répondre

0

Je l'ai essayé sur Linux Fedora PHP 5.2.6 et il semble fonctionner correctement. La sortie est:

[[email protected] ~]$ php -f z.php 
title="My Little Website" 
    year="2007" 
    description="Basic website with ..." 
    tech="PHP, mySQL" 
    link="<a href=\"http://test.com\">test.com</a>" 
+0

Curieux, car il ne fonctionne pas sur le mien - Ubuntu 9.10 avec PHP 5.2.10 –

0

Que diriez-vous comme ça?

preg_match_all('/(\w+)\s*=\s*"((?:.*?\"?)*)"/', $parStr, $matches, PREG_SET_ORDER); 

Son me donner comme ça

[1] => link 
[2] => <a href=\"http://test.com\">test.com</a> 

Inside [], tout considérer comme unique char,

pour [^\\"], cela ne signifie pas EXCEPT \", sa moyenne EXCEPT \ ET EXCEPT "

MISE À JOUR pour plusieurs valeurs identiques Ligne

preg_match_all('/(\w+)\s*=\s*"((?:[^\\\]*?(?:\\\")?)*?)"/', $parStr, $matches, PREG_SET_ORDER); 

Source String, Exemple

$ parStr = « title = "Mon petit site" année = "2007" description = "site de base avec ..." technologie = » PHP, mySQL "tech =" PHP, MySQL " link =" http: //test.com \ "> test.com" link = "http: //test.com \"> test.com "tech =" PHP , mySQL " ";

Matches,

Array 
(
    [0] => Array 
     (
      [0] => title="My Little Website" 
      [1] => title 
      [2] => My Little Website 
     ) 

    [1] => Array 
     (
      [0] => year="2007" 
      [1] => year 
      [2] => 2007 
     ) 

    [2] => Array 
     (
      [0] => description="Basic website with ..." 
      [1] => description 
      [2] => Basic website with ... 
     ) 

    [3] => Array 
     (
      [0] => tech="PHP, mySQL" 
      [1] => tech 
      [2] => PHP, mySQL 
     ) 

    [4] => Array 
     (
      [0] => tech="PHP, mySQL" 
      [1] => tech 
      [2] => PHP, mySQL 
     ) 

    [5] => Array 
     (
      [0] => link="<a href=\"http://test.com\">test.com</a>" 
      [1] => link 
      [2] => <a href=\"http://test.com\">test.com</a> 
     ) 

    [6] => Array 
     (
      [0] => link="<a href=\"http://test.com\">test.com</a>" 
      [1] => link 
      [2] => <a href=\"http://test.com\">test.com</a> 
     ) 

    [7] => Array 
     (
      [0] => tech="PHP, mySQL" 
      [1] => tech 
      [2] => PHP, mySQL 
     ) 

) 

Personnellement, je se sent comme l'analyse syntaxique HTML avec regex, pas vraiment aimé, mais je ne vois pas d'autre possibilité de vous suggérer, il est donc juste une façon rapide et sale . Pour un gros projet ou de gros fichiers, je vous suggère de trouver un vrai analyseur pour cela.

+0

Ce code ne fonctionne pas quand il y a plusieurs chaînes entre guillemets sur une seule ligne. Il ne parvient pas à trouver la deuxième citation de clôture. Je pense que le problème est dans \ "?, le? Ne concerne que le", mais pas le \. –

+0

J'ai ajouté une autre regex – YOU

2

Je ne sais pas pourquoi cela ne fonctionne pas pour une version particulière de php, mais en utilisant l'idée d'un match non-gourmand, je suis venu avec cette chaîne qui fonctionne:

"(.*?[^\\\])" 

Il Non-avide correspond à tout jusqu'à ce qu'il rencontre un dbl-citation qui n'est pas précédé par un caractère d'échappement. Pour une raison particulière, trois barres obliques inverses sont nécessaires ou php se plaint d'un support inégalé. Je pense que sa présence nécessite un backslash pour précéder le support, mais je ne suis pas sûr. Quelqu'un peut-il confirmer pourquoi trois barres obliques inverses sont nécessaires?

/éditer la limite de blanc

+0

Fonctionne bien pour moi PHP-5.3/Ubuntu-11.10, a dû essayer toutes les autres solutions d'abord. @Scott: sans la 3ème barre oblique inversée, le signe de fin] n'est pas reconnu – 4levels

+0

Techniquement, il pourrait s'agir de quatre barres obliques. Slash entre guillemets échappe au caractère suivant, et \\ est équivalent à \, essayez depuis la ligne de commande: php -r 'echo "(. *? [^ \\\]) \ n"; echo "(. * ? [^ \\\\]) \ n "; ' – razzed

Questions connexes