2010-12-14 35 views
1

Je me demandais s'il y a un moyen d'avoir cetteRegex pour trouver la dernière jeton sur une chaîne

var string = "foo::bar" 

Pour la dernière partie de la chaîne: "bar" en utilisant seulement regex.

J'essayais de faire des anticipations, mais je ne pouvais pas les maîtriser assez pour le faire.

-

MISE À JOUR

Peut-être que quelques exemples feront la question plus claire.

var st1 = "foo::bar::0" 
match should be 0 

var st2 = "foo::bar::0-3aab" 
match should be 0-3aab 

var st3 = "foo" 
no match should be found 
+0

comme séparateur, je veux avoir tout ce qui suit la dernière section '::', pourrait être qu'après le '::' j'ai un autre type de symbole, nombre, etc. – jpabluz

+0

Le dernier jeton peut-il contenir ':'? Si oui, peut-il être 'foo ::: bar', et comment allez-vous le gérer? – Kobi

Répondre

8

Vous pouvez utiliser un négatif préanalyse:

/::(?!.*::)(.*)$/ 

Le résultat sera alors dans la capture.

Une autre approche:

/^.*::(.*)$/ 

Cela devrait fonctionner parce que les .* matchs avidement, de sorte que le :: correspondra à la dernière occurence de cette chaîne.

+0

Et si vous avez des espaces de fin, ou peut avoir ou non des espaces de fin, essayez plutôt "\\ w + \\ s * $". –

+0

Cela ne fonctionnera pas pour mes exemples, car il correspondra à "bar :: 0" dans le premier exemple. – jpabluz

+0

Cela ne marchera pas - '*' est gourmand, et va donc, par exemple, faire correspondre 'bar :: 0-3aab' dans' foo :: bar :: 0-3aab'. –

2

Simplement,

/::(.+)$/ 

Vous ne pouvez pas utiliser lookaheads sauf si vous savez exactement combien de temps une chaîne que vous essayez de faire correspondre. Heureusement, ce n'est pas un problème, car vous ne regardez que la fin de la chaîne $.

+0

Cela ne fonctionnera pas pour mes exemples, à cela il va correspondre "bar :: 0" dans le premier exemple. – jpabluz

+0

Cela ne marchera pas - '+ 'est gourmand, et va donc, par exemple, faire correspondre' bar :: 0-3aab' dans 'foo :: bar :: 0-3aab'. –

+0

Désolé, cela ne fonctionnera toujours pas, mais pas pour la raison que j'ai dite. –

0
var string2 = string.replace(/.*::/, ""); 

mais peut-être string est pas le meilleur choix de nom pour votre chaîne?

+0

haha ​​oui, le nom était juste à titre illustratif. =) – jpabluz

1

Je n'utiliserais pas d'expressions régulières pour cela (bien que vous le puissiez certainement); Je diviserais la chaîne sur ::, puisque c'est conceptuellement ce que vous voulez faire.

function lastToken(str) { 
    var xs = str.split('::'); 
    return xs.length > 1 ? xs.pop() : null; 
} 

Si vous voulez vraiment juste une expression régulière, vous pouvez utiliser /::((?:[^:]|:(?!:))*)$/. Tout d'abord, il correspond à un littéral ::. Ensuite, nous utilisons des parenthèses pour mettre la chose désirée dans la capture du groupe 1. La chose désirée est une ou plusieurs copies d'une chaîne -bracketed (?:...); ce groupe de bracketing sans capture. Nous recherchons ensuite soit [^:], un caractère non-deux-points, soit :(?!:), un deux-points suivi d'un non-deux-points. Le (?!...) est un lookahead négatif, qui ne correspond que si le jeton suivant ne correspond pas au motif contenu. Depuis JavaScript ne supporte pas les négatifs d'assertions arrières, je ne vois pas un bon moyen d'éviter de capturer le :: aussi bien, mais vous pouvez envelopper ceci en fonction:

function lastTokenRegex(str) { 
    var m = str.match(/::((?:[^:]|:(?!:))*)$/); 
    return m && m[1]; 
}