2015-04-28 2 views
1

Je suis en train de créer un programme Java pour réécrire des classes Java obsolètes dans notre logiciel. Une partie de la conversion consiste à remplacer les noms de variables par des traits de soulignement plutôt que d'utiliser camelCase. Le problème est, je ne peux pas simplement remplacer tous les traits de soulignement dans le code. Nous avons quelques classes avec des constantes et pour celles-ci, le trait de soulignement devrait rester.
Comment puis-je remplacer des instances telles que string_label avec stringLabel, mais ne remplacez PAS les underscores qui se produisent après le préfixe "Parameters."?Java Regex soulignement à chameau à l'exception de certains préfixes

EDIT:
J'utilise actuellement ce qui suit qui, évidemment, ne traite pas l'exclusion de certains préfixes:

public String stripUnderscores(String line) { 
    Pattern p = Pattern.compile("_(.)"); 
    Matcher m = p.matcher(line);   
    StringBuffer sb = new StringBuffer(); 
    while(m.find()) { 
    m.appendReplacement(sb, m.group(1).toUpperCase()); 
    } 
    m.appendTail(sb); 
    return sb.toString(); 
} 
+1

Y a-t-il une question ici? Cela ressemble plus à un rapport d'état qu'à une demande d'aide. Je ne vois pas de point d'interrogation ou de déclaration sur le problème réel que vous avez, ni sur ce que vous avez essayé. – dcsohl

+0

Quelle est la règle actuelle? Tout identifiant qualifié avec 'Parameters'? Qu'en est-il de la classe 'Parameters' où un identifiant pourrait être référencé avec un nom simple? – Radiodef

+0

Je pensais qu'il était assez clair que je suis capable de remplacer quelque chose comme "_a" avec "A", mais je ne sais pas comment sauter les instances où les traits de soulignement se produisent directement après un préfixe spécifique. – Tommo

Répondre

2

Vous pourriez peut-être essayer quelque chose comme:

Pattern.compile("(?<!(class\\s+Parameters.+|Parameters\\.[\\w_]+))_(.)") 

qui utilise un negative lookbehind.

Vous seriez probablement mieux servi en utilisant une sorte d'outil de refactoring qui comprenait la sémantique de portée.

Si tout ce que vous vérifier est un nom qualifié comme Parameters.is_module_installed vous remplacera

class Parameters { 
    static boolean is_module_installed; 
} 

par erreur. Et il y a plus de cas d'angle comme celui-ci. (import static Parameters.*;, etc., etc.)

L'utilisation d'expressions régulières seule me semble gênante. Une façon vous pouvez faire le plus intelligent de routine est d'utiliser regex juste pour capturer une expression d'identifiants et vous pouvez l'examiner séparément:

static List<String> exclude = Arrays.asList("Parameters"); 

static String getReplacement(String in) { 
    for(String ex : exclude) { 
     if(in.startsWith(ex + ".")) 
      return in; 
    } 

    StringBuffer b = new StringBuffer(); 
    Matcher m = Pattern.compile("_(.)").matcher(in); 
    while(m.find()) { 
     m.appendReplacement(b, m.group(1).toUpperCase()); 
    } 

    m.appendTail(b); 
    return b.toString(); 
} 

static String stripUnderscores(String line) { 
    Pattern p = Pattern.compile("([_$\\w][_$\\w\\d]+\\.?)+"); 
    Matcher m = p.matcher(line);   
    StringBuffer sb = new StringBuffer(); 
    while(m.find()) { 
     m.appendReplacement(sb, getReplacement(m.group())); 
    } 
    m.appendTail(sb); 
    return sb.toString(); 
} 

Mais qui va encore échouer pour exemple class Parameters { is_module_installed; }.

Il pourrait être plus robuste en brisant plus bas chaque expression:

static String getReplacement(String in) { 
    if(in.contains(".")) { 
     StringBuilder result = new StringBuilder(); 

     String[] parts = in.split("\\."); 

     for(int i = 0; i < parts.length; ++i) { 
      if(i > 0) { 
       result.append("."); 
      } 

      String part = parts[i]; 

      if(i == 0 || !exclude.contains(parts[i - 1])) { 
       part = getReplacement(part); 
      } 

      result.append(part); 
     } 

     return result.toString(); 
    } 

    StringBuffer b = new StringBuffer(); 
    Matcher m = Pattern.compile("_(.)").matcher(in); 
    while(m.find()) { 
     m.appendReplacement(b, m.group(1).toUpperCase()); 
    } 

    m.appendTail(b); 
    return b.toString(); 
} 

qui traiterait une situation comme

Parameters.a_b.Parameters.a_b.c_d 

et sortie

Parameters.a_b.Parameters.a_b.cD 

C'est la syntaxe Java impossible mais j'espère que vous voyez ce que je veux dire. Faire un peu d'analyse va un long chemin.

+0

Je comprends cela. Le but est de vraiment remplacer les noms de champs qui ont été définis en utilisant _ au lieu de chameau sans changer les champs/constantes qui existent d'une autre classe. – Tommo

+1

Voir ma modification. Mon idée de lookbehind n'a pas fonctionné de toute façon. – Radiodef

+0

Cela fait exactement ce dont j'ai besoin! Je vous remercie. Après avoir examiné toutes les instances que j'ai besoin d'être remplacées, je pense presque que chaque fois que le match commence par un point, quel que soit le préfixe, je ne veux pas le remplacer car cela signifie probablement qu'il s'agit d'un champ/méthode une autre classe. – Tommo

0

Peut-être que vous pouvez avoir un autre motif:

Pattern p = Pattern.compile("^Parameters.*"); //^ means the beginning of a line 

Si cela correspond, n » t remplacer quoi que ce soit.

+0

Désolé pour négligence, cela pourrait être plus approprié: \\ bParameters. *? \\ b (\\ b signifie limite de mot.) –