2008-12-15 6 views
1

Je voudrais construire une expression rationnelle en Java qui serait passée dans un FilenameFilter pour filtrer les fichiers dans un répertoire.Java regexp pour le filtrage de fichiers

Le problème est que je ne peux pas obtenir le coup de l'expression rationnelle « modèle mental » :)

C'est que je suis venu regexp avec pour sélectionner les fichiers que je voudrais exclure

((ABC | XYZ)) + \ w * Test.xml

Ce que je voudrais faire est de sélectionner tous les fichiers qui se terminent par Test.xml mais ne commencent pas par ABC ou XYZ.

Pourriez-vous s'il vous plaît ajouter des ressources qui pourraient m'aider dans ma bataille avec les expressions rationnelles.

Merci

La ressource suivante explique beaucoup de choses sur regexp regular-expressions.info

+2

Vous avez maintenant deux problèmes. –

Répondre

4

Ce que je voudrais faire est de sélectionner tous les fichiers qui se terminent par Test.xml mais ne commencent pas par ABC ou XYZ.

Soit vous correspondent tous vos fichiers avec cette regex:

^(?:(?:...)(?<!ABC|XYZ).*?)?Test\.xml$ 

ou vous faites le contraire, et prendre tous les fichiers qui ne pas match:

^(?:ABC|XYZ).*?Test\.xml$ 

Personnellement, je trouver la deuxième alternative beaucoup plus simple.

 
ABC_foo_Test.xml // #2 matches 
XYZ_foo_Test.xml // #2 matches 
ABCTest.xml  // #2 matches 
XYZTest.xml  // #2 matches 
DEF_foo_Test.xml // #1 matches 
DEFTest.xml  // #1 matches 
Test.xml   // #1 matches 
+0

+1 pour vos deux regex, j'ai fixé le mien (voir commentaires) – VonC

9

Ce truc est plus facile, plus rapide et plus facile à lire sans regexes.

if (str.endsWith("Test.xml") && !str.startsWith("ABC")) 
1

Juste pour le plaisir de la regex:

(?ms)^([^\r\n]{3}(?<!ABC|XYZ)[^\r\n]*?)?Test\.xml$ 

Même si ce n'est pas la solution la plus facile à lire, qui devrait fonctionner, et qui vous évitera de définir votre propre filtre de fichier personnalisé.

(?<!ABC|XYZ) est une expression de renvoi qui évite que le quatrième caractère (après les trois premiers caractères) soit précédé de ce que vous voulez éviter.

+0

Cela ne fonctionne pas pour "DEFTest.xml" ou "Test.xml". – Tomalak

+0

@Tomalak: Merci, je viens de corriger mon regex et +1 à la vôtre (même si je préfère [\ r \ n] à '.'. – VonC

+0

Mais dans ce cas: les noms de fichiers ne peuvent pas contenir de sauts de ligne. En mode normal, le point ne correspond pas aux caractères de nouvelle ligne, utiliser [^ \ r \ n] me semble donc trop compliqué – Tomalak

0

Cela permet de sélectionner des fichiers qui ne commencent pas en A, B, C, X, Y ou Z, et cette fin Test.xml.

« [^ ABCXYZ] * \ Test \ .xml \\ z »

  • [^]: ABCXYZ tout caractère non dans l'ensemble A, B, C, X, Y, Z.
  • *:. pas de caractère, zéro ou plusieurs fois
  • Test: Le texte exact "Test"
  • \\: Le caractère point (besoin d'échapper en utilisant backslash, et si vous êtes dans une chaîne, cette barre oblique inverse doit être échappée ...par une barre oblique inverse)
  • xml: Le texte exact "xml"
  • \\ z: La fin de l'entrée
+0

Ce n'était pas la question, j'en ai peur. Cela ne correspond pas à "ACD_Test.xml", bien que cela doive l'être, et les doubles barres obliques inverses sont incorrectes pour regex, elles sont une exigence de langage de programmation. – Tomalak

+0

L'OP a dit qu'il s'agit d'une expression rationnelle Java, et dans les littéraux de chaînes Java, les antislashs dans les séquences d'échappement regex doivent être doublés. Cependant, la classe de caractères niée au début est définitivement fausse. –

1

Les regexes fournies par Tomalak et VonC sont plus compliquées qu'elles ne doivent être. Mettre une anticipation négative au début de la regex est beaucoup plus clair que de faire correspondre trois caractères et de faire un lookbehind négatif. Et si vous utilisez la méthode matches(), vous n'avez même pas besoin d'utiliser des ancres (^, $, \z).

public boolean accept(File dir, String name) { 
    return name.matches("(?!ABC|XYZ).*Test\\.xml"); 
}