2009-10-07 9 views
11

J'espère que cela devrait être rapide et simple, en utilisant PHP J'essaie de diviser une chaîne en un tableau mais uniquement par la dernière instance d'un espace. Jusqu'ici j'ai ...Regex pour diviser une chaîne uniquement par le dernier caractère d'espace

$str="hello this is  a space"; 
$arr=preg_split("/\s+/",$str); 
print_r($arr); 

Array ([0] => hello [1] => this [2] => is [3] => a [4] => space) 

... qui se divise par toutes les instances d'espaces.

Comment puis-je développer cette expression régulière pour la diviser uniquement par la dernière instance d'un espace? Pour devenir ...

Array ([0] => hello this is  a [1] => space) 

Merci d'avance de votre aide!

Répondre

36

Essayez:

$arr=preg_split("/\s+(?=\S*+$)/",$str); 

Modifier

Une brève explication:

Le (?= ...) est appelé look ahead positif. Par exemple, a(?=b) ne correspondra qu'à un seul 'a' si le caractère suivant (celui qui se trouve à sa droite) est 'b'. Notez que le 'b' est et non une partie du match!

Le \S est juste un raccourci pour le character class[^\s]. En d'autres termes: il correspond à un seul caractère autre qu'un caractère d'espace blanc. Le + après le * rend la classe de caractères \Spossessive.

Enfin, le $ indique la fin de la chaîne.

Pour résumer, l'expression rationnelle complète \s+(?=\S*+$) lirait en anglais simple comme suit:

apparier un ou plusieurs caractères d'espace blanc que quand on regarde devant ces caractères blancs zéro ou plusieurs caractères autres que des caractères blancs , suivi par la fin de la chaîne, peut être vu.

+0

Excellent, merci, cela fonctionne parfaitement. Juste pour comprendre, pourriez-vous expliquer comment la partie '(? = \ S * + $)' de cette expression fonctionne s'il vous plaît? – chattsm

+0

De rien Martin. Voir le 'edit' pour une explication. –

+0

C'est génial Bart, merci. Je te donnerais plus de points si je le pouvais! – chattsm

2

Cela devrait fonctionner:

$str="hello this is a space"; 

preg_match('~^(.*)\s+([^\s]+)$~', $str, $matches); 
$result = array($matches[1], $matches[2]); 

Vous pouvez le faire sans regex:

$parts = array_map('trim', explode(' ', $str)); 
$result = array(
    implode(' ', array_slice($parts, 0, -1)), 
    end($parts) 
); 

ou

$lastSpace = strrpos($str, ' '); 
$str1 = trim(substr($str, 0, $lastSpace)); 
$str2 = trim(substr($str, $lastSpace)); 
$result = array($str1, $str2); 
+0

Merci Tom, deux solutions alternatives intelligentes. – chattsm

0

Si le * et + après \S dupicated? Seulement /\s+(?=\S+$)/ ou /\s+(?=\S*$)/ est assez dépend du besoin.

+0

Non dupliqué - le '* +' est une commande unique, et '\ S * +' peut souvent être plus efficace que faire '\ S *'. Lisez les «quantificateurs possessifs» pour plus de détails. –

Questions connexes