En javascript, existe-t-il un équivalent de String.indexOf () qui prend une expression régulière au lieu d'une chaîne pour le premier premier paramètre tout en autorisant un deuxième paramètre?
Je dois faire quelque chose comme
str.indexOf(/[abc]/ , i);
et
str.lastIndexOf(/[abc]/ , i);
Alors que String.search () prend une expression rationnelle comme paramètre, il ne me permet pas de spécifier un deuxième argument!
Edit:
Cela s'est avéré plus difficile que je ne le pensais à l'origine, j'ai donc écrit une petite fonction de test pour tester toutes les solutions fournies ... cela suppose que regexIndexOf et regexLastIndexOf ont été ajoutés à l'objet String.
function test (str) {
var i = str.length +2;
while (i--) {
if (str.indexOf('a',i) != str.regexIndexOf(/a/,i))
alert (['failed regexIndexOf ' , str,i , str.indexOf('a',i) , str.regexIndexOf(/a/,i)]) ;
if (str.lastIndexOf('a',i) != str.regexLastIndexOf(/a/,i) )
alert (['failed regexLastIndexOf ' , str,i,str.lastIndexOf('a',i) , str.regexLastIndexOf(/a/,i)]) ;
}
}
et je teste comme suit pour m'assurer qu'au moins pour une expression rationnelle de caractère, le résultat est le même que si nous utilisions indexOf
// Recherchez le a parmi le
test xes ('xxx');
test («axx»);
test («xax»);
test («xxa»);
test («axa»);
test («xaa»);
test («aax»);
test («aaa»);
la source
|
l'intérieur[ ]
correspond au caractère littéral|
. Vous vouliez probablement dire[abc]
.Réponses:
En combinant quelques-unes des approches déjà mentionnées (l'indexOf est évidemment assez simple), je pense que ce sont les fonctions qui feront l'affaire:
Évidemment, la modification de l'objet String intégré enverrait des drapeaux rouges pour la plupart des gens, mais cela peut être une fois où ce n'est pas si grave; soyez simplement au courant.
MISE À JOUR: Modifié de
regexLastIndexOf()
sorte que cela semble imiterlastIndexOf()
maintenant. Veuillez me faire savoir si cela échoue toujours et dans quelles circonstances.MISE À JOUR: passe tous les tests trouvés dans les commentaires sur cette page, et le mien. Bien sûr, cela ne signifie pas qu'il est à l'épreuve des balles. Toute rétroaction appréciée.
la source
regexLastIndexOf
ne renverra que l'index de la dernière correspondance sans chevauchement .regex.lastIndex = result.index + 1;
au lieu deregex.lastIndex = ++nextStop;
. Il se passera au prochain match beaucoup plus rapidement, espérons-le, sans perdre aucun résultat.Les instances du
String
constructeur ont une.search()
méthode qui accepte un RegExp et renvoie l'index de la première correspondance.Pour démarrer la recherche à partir d'une position particulière (en simulant le deuxième paramètre de
.indexOf()
), vous pouvezslice
désactiver les premiersi
caractères:Mais cela obtiendra l'index dans la chaîne la plus courte (après que la première partie a été coupée), vous voudrez donc ajouter la longueur de la partie coupée (
i
) à l'index retourné s'il ne l'était pas-1
. Cela vous donnera l'index dans la chaîne d'origine:la source
function regexIndexOf(text, offset) { var initial = text.substr(offset).search(/re/); if(initial >= 0) { initial += offset; } return initial; }
J'ai une version courte pour vous. Ça marche bien pour moi!
Et si vous voulez une version prototype:
EDIT : si vous souhaitez ajouter la prise en charge de fromIndex
Pour l'utiliser, aussi simple que cela:
la source
startIndex
paramètre comme d'habitudeindeoxOf
et lelastIndexOf
faire.startIndex
(oufromIndex
). J'espère que ça aide!lastIndexOfRegex
devrait également ajouter la valeur defromIndex
au résultat."aRomeo Romeo".indexOfRegex(new RegExp("\\bromeo", 'gi'));
Le résultat sera 1 alors qu'il devrait être 7, car indexOf recherchera pour la première fois le "romeo" apparaît, peu importe qu'il soit au début d'un mot ou non.Utilisation:
Voir la documentation ici.
la source
0
, et a été publiée ... sept ans plus tard.Basé sur la réponse de BaileyP. La principale différence est que ces méthodes retournent
-1
si le modèle ne peut pas être mis en correspondance.Edit: Grâce à la réponse de Jason Bunting, j'ai eu une idée. Pourquoi ne pas modifier la
.lastIndex
propriété de l'expression régulière? Bien que cela ne fonctionne que pour les modèles avec le drapeau global (/g
).Edit: mis à jour pour passer les cas de test.
la source
Vous pouvez utiliser substr.
la source
RexExp
les instances ont déjà une propriété lastIndex (si elles sont globales) et donc ce que je fais est de copier l'expression régulière, de la modifier légèrement pour l'adapter à nos besoins, de laexec
placer sur la chaîne et de regarder lelastIndex
. Ce sera inévitablement plus rapide que de boucler sur la chaîne. (Vous avez suffisamment d'exemples sur la façon de mettre cela sur le prototype de chaîne, non?)Vous pouvez également prototyper les fonctions sur l'objet RegExp:
Une explication rapide de la façon dont je modifie le
RegExp
: carindexOf
je dois simplement m'assurer que le drapeau global est défini. Pour,lastIndexOf
j'utilise une anticipation négative pour trouver la dernière occurrence, sauf si leRegExp
correspondait déjà à la fin de la chaîne.la source
Ce n'est pas natif, mais vous pouvez certainement ajouter cette fonctionnalité
Je n'ai pas testé complètement ces méthodes, mais elles semblent fonctionner jusqu'à présent.
la source
Après que toutes les solutions proposées ont échoué mes tests d'une manière ou d'une autre, (modifier: certaines ont été mises à jour pour passer les tests après avoir écrit ceci) J'ai trouvé l'implémentation mozilla pour Array.indexOf et Array.lastIndexOf
J'ai utilisé ceux-ci pour implémenter ma version de String.prototype.regexIndexOf et String.prototype.regexLastIndexOf comme suit:
Ils semblent passer les fonctions de test que j'ai fournies dans la question.
De toute évidence, ils ne fonctionnent que si l'expression régulière correspond à un caractère, mais cela suffit pour mon objectif car je vais l'utiliser pour des choses comme ([abc], \ s, \ W, \ D)
Je continuerai à surveiller la question au cas où quelqu'un fournirait une implémentation meilleure / plus rapide / plus propre / plus générique qui fonctionne sur n'importe quelle expression régulière.
la source
J'avais également besoin d'une
regexIndexOf
fonction pour un tableau, donc j'en ai programmé une moi-même. Cependant, je doute qu'il soit optimisé, mais je suppose que cela devrait fonctionner correctement.la source
Dans certains cas simples, vous pouvez simplifier votre recherche en arrière en utilisant le fractionnement.
Cela a quelques problèmes graves:
Mais du bon côté, c'est beaucoup moins de code. Pour une expression régulière de longueur constante qui ne peut pas se chevaucher (comme
/\s\w/
pour trouver des limites de mots), cela suffit.la source
Pour les données avec des correspondances clairsemées, l'utilisation de string.search est la plus rapide parmi les navigateurs. Il retaille une chaîne à chaque itération pour:
Pour les données denses, je l'ai fait. C'est complexe par rapport à la méthode d'exécution, mais pour les données denses, c'est 2 à 10 fois plus rapide que toutes les autres méthodes que j'ai essayées et environ 100 fois plus rapide que la solution acceptée. Les points principaux sont:
La nouvelle expression régulière est exécutée et les résultats de cet exécutable ou du premier exécutable sont renvoyés;
jsPerf des méthodes
Je ne comprends pas le but des tests en haut. Les situations qui nécessitent une expression régulière sont impossibles à comparer avec un appel à indexOf, ce qui, à mon avis, est le point de faire la méthode en premier lieu. Pour réussir le test, il est plus logique d'utiliser «xxx + (?! X)» que d'ajuster la manière dont l'expression régulière s'exprime.
la source
Le dernier index de Jason Bunting ne fonctionne pas. Le mien n'est pas optimal, mais ça marche.
la source
Il n'y a toujours pas de méthodes natives qui effectuent la tâche demandée.
Voici le code que j'utilise. Il imite le comportement des méthodes String.prototype.indexOf et String.prototype.lastIndexOf mais ils acceptent également un RegExp comme argument de recherche en plus d'une chaîne représentant la valeur à rechercher.
Oui, la réponse est assez longue car elle essaie de suivre les normes actuelles aussi près que possible et contient bien sûr un nombre raisonnable de commentaires JSDOC . Cependant, une fois minifié, le code n'est que de 2,27 Ko et une fois compressé pour la transmission, il n'est que de 1023 octets.
Les 2 méthodes auxquelles cela s'ajoute
String.prototype
(en utilisant Object.defineProperty lorsque disponible) sont:searchOf
searchLastOf
Il passe tous les tests publiés par l'OP et, en plus, j'ai testé les routines de manière assez approfondie dans mon utilisation quotidienne, et j'ai essayé de m'assurer qu'elles fonctionnent dans plusieurs environnements, mais les commentaires / problèmes sont toujours les bienvenus.
la source
Si vous recherchez une recherche lastIndex très simple avec RegExp et ne vous souciez pas si elle imite lastIndexOf dans les moindres détails, cela peut attirer votre attention.
J'inverse simplement la chaîne et soustrais le premier indice d'occurrence de la longueur - 1. Il se trouve que je réussis mon test, mais je pense qu'il pourrait y avoir un problème de performances avec les chaînes longues.
la source
J'ai utilisé
String.prototype.match(regex)
qui retourne un tableau de chaînes de toutes les correspondances trouvées de la donnéeregex
dans la chaîne (plus d'informations voir ici ):la source
Utilisez des expressions régulières standard:
la source
Eh bien, comme vous cherchez simplement à faire correspondre la position d'un personnage , l'expression régulière est probablement exagérée.
Je suppose que tout ce que vous voulez c'est, au lieu de "trouver en premier de ce personnage", il vous suffit de trouver en premier de ces personnages.
Bien sûr, c'est la réponse simple, mais fait ce que votre question vise à faire, bien que sans la partie regex (parce que vous n'avez pas clarifié pourquoi spécifiquement il devait être une regex)
la source