2010-12-08 4 views
2

Mon groupe peut être de la forme x/y, x.y ou x_y.z. Chaque groupe est séparé par un trait de soulignement. Les groupes sont non ordonnés.Regex pour capturer des groupes

Exemple:

ABC/DEF_abc.def_PQR/STU_ghi_jkl.mno 

je voudrais saisir les éléments suivants:

ABC/DEF 
abc.def 
PQR/STU 
ghi_jkl.mno 

Je l'ai fait en utilisant une méthode itération de chaîne assez bavard et l'analyse syntaxique (ci-dessous), mais me demande si une simple regex peut accomplir cela.

private static ArrayList<String> go(String s){ 
    ArrayList<String> list = new ArrayList<String>(); 
    boolean inSlash = false; 
    int pos = 0 ; 
    boolean inDot = false; 
    for(int i = 0 ; i < s.length(); i++){ 
     char c = s.charAt(i); 
     switch (c) { 
     case '/': 
      inSlash = true; 
      break; 
     case '_': 
      if(inSlash){ 
       list.add(s.substring(pos,i)); 
       inSlash = false; 
       pos = i+1 ; 
      } 
      else if (inDot){ 
       list.add(s.substring(pos,i)); 
       inDot = false; 
       pos = i+1; 
      } 
      break; 
     case '.': 
      inDot = true; 
      break; 
     default: 
      break; 
     } 

    } 
    list.add(s.substring(pos)); 
    System.out.println(list); 
    return list; 
} 
+0

Le trait de soulignement peut être délimiteur comme ainsi dans le cadre d'un groupe ?? –

+0

La difficulté semble être dans le dernier type de groupe (avec le trait de soulignement). Pourriez-vous élaborer un peu sur les règles pour savoir quand un trait de soulignement devrait faire partie d'un groupe, et quand il devrait être le caractère de séparation? Peut-être pourriez-vous poster votre code actuel. – Jordi

+0

oui, c'est la partie amusante :) Peut-être un moyen de regarder en avant pour un point et ensuite déterminer s'il s'agit d'un delim ou d'un groupe? – dogbane

Répondre

2

avoir un essai avec:

((?:[^_./]+/[^_./]+)|(?:[^_./]+\.[^_./]+)|(?:[^_./]+(?:_[^_./]+)+\.[^_./]+)) 

Je ne sais pas la syntaxe Java mais en Perl:

#!/usr/bin/perl 
use 5.10.1; 
use strict; 
use warnings; 

my $str = q!ABC/DEF_abc.def_PQR/STU_ghi_jkl.mno_a_b_c.z_a_b_c_d.z_a_b_c_d_e.z!; 
my $re = qr!((?:[^_./]+/[^_./]+)|(?:[^_./]+\.[^_./]+)|(?:[^_./]+(?:_[^_./]+)+\.[^_./]+))!; 
while($str=~/$re/g) { 
    say $1; 
} 

produira:

ABC/DEF 
abc.def 
PQR/STU 
ghi_jkl.mno 
a_b_c.z 
a_b_c_d.z 
a_b_c_d_e.z 
+0

Super, ça marche! Est-il possible de changer la dernière partie afin qu'elle puisse correspondre aux formes a_b_c.z, a_b_c_d.z, a_b_c_d_e.z etc? – dogbane

+0

Oui c'est, voir ma réponse mise à jour. – Toto

+0

Les regexes Java sont * en apparence * très semblables aux expressions rationnelles de Perl 5.0 d'environ 1993, mais supportent quelques fonctionnalités plus récentes comme la correspondance possessive. Ils ne supportent aucune des constructions modernes. La similitude apparente est un cas de faux-parents-de * faux amis * pour ainsi dire. ** Ils ne fonctionnent pas correctement sur Unicode ** sans [cette correction] (http://training.perl.com/scripts/tchrist-unicode-charclasses__alpha.java), et leur '\ b' et' \ B' sont si terriblement cassés que des chaînes comme 'élève 'ne vont pas en Java correspondre au modèle'/\ b \ w + \ b/'(' '\\ b \\ w + \\ b" ') ** n'importe où du tout **. Au moins, pas sans ma solution. – tchrist

0

Il peut y avoir un problème avec le trait de soulignement car ce n'est pas toujours un séparateur.

Peut-être: ((?<=_)\w+_)?\w+[./]\.w+

+0

S'il vous plaît soyez extrêmement prudent en utilisant '\ w' dans les expressions régulières Java: c'est [presque toujours faux] (http://stackoverflow.com/questions/4304928/unicode-equivalents-for-w-and- b-in-java-regular-expressions/4307261 # 4307261). ☹ – tchrist

+0

Je suivais juste le javadoc à 'java.util.regex.Pattern'. :) – TomaszK

+0

Cela fait partie du problème, malheureusement. – tchrist

0

Cette regex probablement pas (testé avec des expressions régulières) .Net:

[a-zA-Z]+[./][a-zA-Z]+|[a-zA-Z]+_[a-zA-Z]+\.[a-zA-Z]+ 

(Si vous savez que votre entrée est bien formé, il n'y a pas besoin de faire correspondre explicitement le séparateur)

+0

N'utilisez pas '[a-zA-Z]' comme synonyme estropié pour '\ pL'. :( – tchrist

+0

@tchrist: Vous avez raison (bien sûr) et je suis fainéant (ce qui est une vertu de programmeur, je me rappelle avoir lu quelque part ...) –

+0

il y a de la paresse et il y a de la paresse. Le bad-paresseux évite le travail maintenant en promettant de travailler (beaucoup) plus dans le futur.La bonne paresse évite le travail dans le futur par un peu de travail supplémentaire maintenant. :) – tchrist

0

Celui-ci va de pair avec préanalyse positive au lieu d'alternances

[A-Za-z]+(_(?=[A-Za-z]+\.[A-Za-z]+))?[A-Za-z]+[/.][A-Za-z]+ 
+0

N'utilisez pas '[A-Z]' ou '[a-z]' dans une regex quand '\ pL' est ce que vous voulez dire, ce qui est généralement le cas. – tchrist

Questions connexes