2010-10-11 10 views
2

J'ai une chaîne contenant plusieurs paramètres, par ex. Pour la sortie de journal, je veux "cacher" certaines valeurs du paramètre, c'est-à-dire les remplacer par ***.Correspondance des valeurs de paramètre dans une chaîne à l'aide de regex

J'utilise l'expression rationnelle suivante pour correspondre à la valeur du paramètre, qui fonctionne très bien pour la plupart des cas:

(PARMANAME=")[\w\s]*" 

Cependant, cette regex correspond uniquement à des espaces blancs et mot: caractères. Je veux l'étendre pour correspondre à tous les caractères entre les deux guillemets. Le problème est que la valeur elle-même peut contenir (échappé) entre guillemets, par exemple .:

PARAM="the name of this param is \"param\"" 

Comment puis-je correspondre (et remplacer) correctement?

Ma Java méthode ressemble à ceci:

/** 
* @param input input string 
* @param params list of parameters to hide 
* @return string with the value of the parameter being replace by *** 
*/ 
public static String hideParamValue(String input, final String... params) 
{ 
    for (String param : params) 
    { 
     input = input.replaceAll("(" + param + "=)\\\"[\\w\\s]*\\\"", "$1***"); 
    } 
    return input; 
} 
+0

Merci pour toutes les bonnes réponses. Ils fonctionnent tous très bien pour mes cas de test. – martin

Répondre

4

citations Escaped sont un véritable PITA en Java, mais cela devrait faire l'affaire:

public class Test 
{ 
    public static String hideParamValue(String input, final String... params) 
    { 
    for (String param : params) 
    { 
     input = input.replaceAll(
     "(" + param + "=)\"(?:[^\"\\\\]|\\\\.)*\"", 
     "$1***"); 
    } 
    return input; 
    } 

    public static void main(String[] args) 
    { 
    String s = "PARAM1=\"a b c\", PARAM2=\"d \\\"e\\\" f\", PARAM3=\"g h i\""; 
    System.out.println(s); 
    System.out.println(hideParamValue(s, "PARAM2", "PARAM3")); 
    } 
} 

sortie:

PARAM1="a b c", PARAM2="d \"e\" f", PARAM3="g h i" 
PARAM1="a b c", PARAM2=***, PARAM3=*** 

[^\"\\\\] correspond à tout caractère autre qu'une guillemet ou une barre oblique inverse.La barre oblique inverse doit être échappée avec une autre barre oblique inversée pour l'expression rationnelle, puis chacun d'entre eux doit être échappé pour la chaîne littérale. Mais le guillemet n'a pas de signification particulière dans une regex, donc il n'a besoin que d'un backslash.

(?:[^\"\\\\]|\\\\.) correspond à tout sauf un guillemet ou une barre oblique inverse, ou une barre oblique inverse suivie quoi que ce soit. Cela prend soin de vos guillemets échappés, et permet également des backslashes échappés et d'autres séquences d'échappement, sans frais supplémentaires. L'approche négative-lookbehind suggérée par @axtavt ne gère que les guillemets échappés et traite \\" comme une barre oblique inverse suivie d'une citation échappée, alors qu'elle était probablement prévue comme une barre oblique inverse échappée suivie d'un guillemet.

1

Essayez cette expression régulière:

PARAM="(?:[^"\\]|\\")*" 

Cela ne permet une séquence soit un caractère à l'exception " et \ ou \". Si vous souhaitez permettre à d'autres séquences d'échappement que juste \", vous pouvez l'étendre avec \\["rnt…] par exemple pour permettre également \r, \n, \t, etc.

1

Vous devez ajouter les guillemets doubles scaped à vos personnages mathing expression:

[\w\s\\"] au lieu de [\w\s] qui a échappé dans votre chaîne se traduira comme [\\w\\s\\\\\"] au lieu de [\\w\\s]

Ainsi, le code final résultera que

/** 
* @param input input string 
* @param params list of parameters to hide 
* @return string with the value of the parameter being replace by *** 
*/ 
public static String hideParamValue(String input, final String... params) { 
    for (String param : params) 
    { 
     input = input.replaceAll("(" + param + "=)\\\"[\\w\\s\\\\\"]*\\\"", "$1***"); 
    } 
    return input; 
} 
1

Un negative lookbehind peut être utile dans ce cas:

(PARAMNAME=").*?(?<!\\)" 

qui est

s.replaceAll("(" + param + "=)\".*?(?<!\\\\)\"", "$1***"); 

(?<!\\)" signifie " pas précédé par \, de sorte que .*?(?<!\\)" signifie la plus courte possible (en raison de reluctant*?) séquence de tous les caractères se terminant par "" est non t précédé de \.