2009-06-24 8 views
2

j'ai le code suivantmots-clés Extrait/balises de chaîne à l'aide preg_match_all

$str = "keyword keyword 'keyword 1 and keyword 2' another 'one more'".'"another keyword" yes,one,two'; 

preg_match_all('/"[^"]+"|[^"\' ,]+|\'[^\']+\'/', $str, $matches); 

echo "<pre>"; print_r($matches); echo "</pre>"; 

Là où je veux extraire des mots-clés d'une chaîne, et de garder ceux enveloppés entre guillemets simples ou doubles ensemble, ce code fonctionne OK , mais il renvoie les valeurs avec les guillemets. Je sais que je peux les enlever via str_replace ou similaire, mais je cherche vraiment un moyen de résoudre ce problème via la fonction preg_match_all.

Sortie:

Array 
(
    [0] => Array 
     (
      [0] => keyword 
      [1] => keyword 
      [2] => 'keyword 1 and keyword 2' 
      [3] => another 
      [4] => 'one more' 
      [5] => "another keyword" 
      [6] => yes 
      [7] => one 
      [8] => two 
     ) 

) 

, je pense aussi mon regex est un peu mièvre être, donc des suggestions pour une meilleure serait serait bien :)

Toute suggestion/aide serait grandement appréciée.

+0

Qu'en est-il quelque chose comme 'a, "b", c, d, "e" ou' ' "b '"'" c'' – Gumbo

Répondre

1

Vous avez presque l'avez; vous avez juste besoin d'utiliser lookarounds pour les citations: correspondre?

'/(?<=\')[^\'\s][^\']*+(?=\')|(?<=")[^"\s][^"]*+(?=")|[^\'",\s]+/' 
+0

Superbe !!!!! C'est exactement ce dont j'avais besoin! Merci beaucoup Alan M. Je viens d'essayer de comprendre l'expression rationnelle que vous avez utilisée, et son début à donner un sens. Pour être honnête, je n'ai jamais rencontré le = avant.Merci encore, vraiment l'apprécier –

+0

Vous pourriez vouloir lire ceci: http://www.regular-expressions.info/lookaround.html Ce site entier est excellent. –

0

Jetez un oeil à this tokenizeQuote function dans les commentaires au strtok function.

Modifier Vous devez modifier la fonction parce que l'original ne fonctionne qu'avec des guillemets doubles:

function tokenizeQuoted($string) 
{ 
    for ($tokens=array(), $nextToken=strtok($string, ' '); $nextToken!==false; $nextToken=strtok(' ')) { 
     $firstChar = $nextToken{0}; 
     if ($firstChar === '"' || $firstChar === "'") { 
      $nextToken = $nextToken{strlen($nextToken)-1} === $firstChar 
       ? substr($nextToken, 1, -1) 
       : substr($nextToken, 1) . ' ' . strtok($firstChar); 
     } 
     $tokens[] = $nextToken; 
    } 
    return $tokens; 
} 

Modifier Peut-être que vous devriez juste écrire votre propre analyseur:

$tokens = array(); 
$buffer = ''; 
$quote = null; 
$len = strlen($str); 
for ($i=0; $i<$len; $i++) { 
    $char = $str{$i}; 
    if ($char === '"' || $char === "'") { 
     if ($quote === null) { 
      if ($buffer !== '') { 
       $tokens[] = $buffer; 
       $buffer = ''; 
      } 
      $quote = $char; 
      continue; 
     } 
     if ($quote == $char) { 
      $tokens[] = $buffer; 
      $buffer = ''; 
      $quote = null; 
      continue; 
     } 
    } else if ($char === ',' || $char === ' ') { 
     if ($quote === null) { 
      if ($buffer !== '') { 
       $tokens[] = $buffer; 
       $buffer = ''; 
      } 
      continue; 
     } 
    } 
    $buffer .= $char; 
} 
if ($buffer !== '') { 
    $tokens[] = $buffer; 
} 
+0

Non tout ce que je recherche, comme je le ferais avec preg_match_all, mais merci (aussi la fonction ne fonctionne pas avec des guillemets simples) –

+0

Mais encore une fois, il ne prend pas en compte les virgules comme mon regex, seulement Je suis convaincu que le meilleur moyen serait d'utiliser preg_match_all, mais si cela ne peut pas être fait, alors je me contenterai d'un substitut –

1
preg_match_all('/"([^"]+)"|[^"\' ,]+|\'([^\']+)\'/',$str,$matches); 

et utilisez $matches[1] et $matches[2].

+0

Il faudrait: preg_match_all ('/ "([^" ] +) "| ([^" \ ',] +) | \' ([^ \ '] +) \'/', $ str, $ correspond); et utilise $ matches [1], $ matches [ 2], et $ matches [3] qui nécessiteraient encore plus de manipulation après le preg_match_a ll fonctionnera, donc il serait plus facile de array_map une fonction str_replace qui fusionnerait l'instance active du tableau en un seul tableau. –

+0

Comment suggéreriez-vous que vous joigniez les différents tableaux de résultats? –

+0

Il n'y a pas de fonction native de fusion de tableaux, donc j'écrirais un, je suppose. Je ne comprends pas très bien quelles sont vos exigences de production, donc il est difficile de dire ce qui est le plus approprié. – chaos

0

cela nécessite une fonction simple pour obtenir ce que vous voulez, mais il fonctionne

preg_match_all('/"([^"]+)"|([^"\' ,]+)|\'([^\']+)\'/',$str,$matches); 
function r($str) { 
    return str_replace(array('\'','"'), array(''), $str); 
} 
$a = array_map('r', $matches[0]); 
print_r($a); 
+0

Merci, j'ai déjà examiné cela mais crée une charge de travail inutile. Merci pour votre contribution si Galen –