2009-08-04 8 views
3

Je travaille sur ce projet de refactoring assez gros et j'utilise la recherche/remplacement d'intellij avec regexp pour m'aider.regex pour cela exclut les correspondances entre guillemets

C'est le regexp J'utilise:

\b(?<!\.)Units(?![_\w(.])\b 

Je trouve que la plupart des matches qui ne sont pas utiles à mon but sont les rencontres qui se produisent avec des chaînes entre guillemets, par exemple: « unités »

Je voudrais trouver un moyen d'avoir l'expression ci-dessus ne correspond pas quand il trouve une chaîne correspondante qui est entre guillemets ...

Thx à l'avance, cet endroit bascule!

+0

En théorie, ce que vous demandez n'est pas possible avec les expressions régulières, car vous devez compter les occurrences de guillemets. Considérons une chaîne comme '" \ "" + Number + "(" + Units ") \" "'. Est-ce que 'Units' est entre guillemets ou non? Ce n'est pas le cas, mais aucune regex ne pourra vous le dire. Vous feriez mieux de trouver une installation qui trouvera contextuellement tous les jetons nommés '' Units '' plutôt que de trouver lexicalement toutes les chaînes correspondant à '' Units ''. – Welbog

+0

hdx a un espace de recherche bien défini - ce n'est pas contradictoire. Il peut très bien être traitable avec un regex. –

+0

Si les guillemets sont juste avant et après le mot comme dans votre exemple ("units"), vous pouvez simplement ajouter des guillemets à vos lookarounds existants. Mais je soupçonne que ce n'est pas ce que tu voulais dire. –

Répondre

2

En supposant que les citations sont toujours apparié sur une ligne donnée, vous pouvez créer des correspondances avant et après un nombre pair de citations, et assurez-vous que la ligne entière est adaptée:

^([^"]*("[^"]*")*[^"]*)*\b(?<!\.)Units(?![_\w(.])\b([^"]*("[^"]*")*[^"]*)*$ 

cela fonctionne parce que le fragment

([^"]*("[^"]*")*[^"]*)* 

ne correspondra qu'aux paires de guillemets. En ajoutant les ancres de début et de fin, cela force les guillemets sur les côtés gauche et droit de votre regex à être un nombre pair.

Ceci ne gérera pas correctement les guillemets d'échappement intégrés, et les chaînes entre guillemets multilignes seront problématiques.

+0

OK, certaines choses manquent à cette expression: tout d'abord, il ne correspond qu'à un caractère entre guillemets. Vous devriez changer le milieu '[^"] 'à' [^ "] *'.Et il ne correspond qu'à une paire de guillemets avant et après 'Units', donc toute l'expression appariée doit être enveloppée dans un groupe et une fermeture de Kleene:' ([^ "] * (" [^ "] *") [^ " ] *) * '. Mais même alors cela ne correspond pas à des cas pathologiques comme celui que j'ai mis dans mon commentaire sur la question:' "\" "+ Number +" ("+ Units") \ "" '. – Welbog

+0

Mise à jour pour refléter les corrections suggérées Les cas pathologiques ont déjà été énumérés dans ma réponse, je ne cherche pas à cacher ignorez les, mais parfois la charge de travail n'a pas de cas pathologiques.Construire un tokenizer est beaucoup plus de travail que d'ajouter quelques douzaines de caractères à une regex.Le logiciel est censé être simple –

+0

Bon retour, je n'ai pas pleine connaissance de chaque IDE là-bas, mais je suis raisonnablement sûr qu'ils viennent déjà avec des analyseurs (pour la coloration syntaxique) qui ont alre ady a segmenté le code et peut facilement rechercher des jetons nommés plutôt que de traiter le code comme une chaîne. Bien que le code de tokenisation de code soit certainement plus compliqué que la plupart des expressions régulières autonomes, il est conceptuellement plus simple d'analyser du code à jetons que de scanner du code sous la forme d'un ensemble de chaînes. Quand je dis «le logiciel est censé être simple», je fais référence à la capacité de comprendre facilement ce qui se passe à un niveau élevé. – Welbog

1

Intellij utilise des expressions rationnelles Java, n'est-ce pas? Essayez ceci:

(?m)(?<![\w.])Units(?![\w(.])(?=(?:[^\r\n"\\]++|\\.)*+[^\r\n"\\]*+$) 

La première partie est votre regex après une petite chirurgie esthétique:

(?<![\w.])Units(?![\w(.]) 

Le \b au début et à la fin étaient effectivement les mêmes en tant que lookbehind négatif et une préanalyse négative (respectivement) pour \w, donc je les ai pliés dans vos lookarounds existants. Le nouveau préanalyse correspond au reste de la ligne si elle contient un nombre pair (y compris zéro) de guillemets unescaped:

(?=(?:[^\r\n"\\]++|\\.)*+[^\r\n"\\]*+$) 

qui gère les cas pathologiques comme celui Welbog dit, et contrairement à la regex de Michael il trouvera plusieurs occurrences du texte la même ligne. Mais il ne prend pas en compte les commentaires. La fonction de recherche/remplacement d'Intellij est-elle assez intelligente pour ne pas tenir compte du texte dans les commentaires? En y réfléchissant, n'y a-t-il pas une sorte de soutien au refactoring?

+2

+1 parce que j'admire votre persévérance à résoudre le mauvais problème avec la mauvaise solution et à vous retrouver avec une réponse qui fonctionne. – Welbog

+0

:) Certaines personnes luttent alligators, je lutte regexes. –

+0

@Welbog lol une belle. Je peux rire parce que nous le faisons tous parfois (et certains le font beaucoup) ;-) – jpswain

Questions connexes