简体   繁体   中英

How to replace matched character String in java?

I have a question about how to replace String when matched character found. In this case, i read java file that contains variable which marked with underscore. Here the java file:

 public int[][] initArray(int rows, int cols, int init_value)
{
 int[][] _bb = (int[][])null;
 if ((rows > 1) && (cols > 1)) {
   _bb = new int[rows][cols];
   for (int _ii = 0; _ii < rows; _ii++) {
     for (int _ee = 0; _ee < cols; _ee++) {
       _bb[_ii][_ee] = init_value;
     }
   }
 } else {
   warning("Array length must be greater than zero!");
 }
 return _bb;
}

All of variable that contain underscore will be replaced with generate string. Well, then this is the code that i have used to read that file and replace matched string:

HashMap<String, String> map = new HashMap<String, String>();

if (line.contains(" _") && line.contains(";")) {

    String get = varname(line);

    RandomString r = new RandomString();

    String[] split = get.split("\\s+");
    String gvarname = split[0];

   ss = "_"+gvarname;
   map.put(ss, "l"+r.generateRandomString());

   for(String key: map.keySet()){
       if(line.contains(key)){
           line = line.replace(key, map.get(key));

       }
   }

Then, this is a method to get an index of variable name:

String varname(String str){
    int startIdx = str.indexOf("_");
    int endIdx = str.indexOf(';');

    String content = str.substring(startIdx + 1, endIdx);
    return content;
}

Actually above code is working and replace some variables name, but some character noted matched when i put space example _bb[_ii] is not working, but _bb[ _ii ] is working. I don't know how, help me!

Thanks

In your first if -statement you check if the string contains " _" (an underscore with a leading space).

If in the following line of your source-java-file

       _bb[_ii][_ee] = init_value;

_bb... is indented with tabulators, <tab>_bb will not match <space>_bb . There is no leading space before _ii and _ee either, so the if returns false .

If you put a space between [ and _ii , you find a match for <space>_ii and your if results in true and executes your replacement code.

If you are sure that there will be no other use of an underscore in your source text other than as a replacement indicator, you can simply remove the space from your if-condition and use line.contains("_") instead.

Btw: Are you sure that you want to check that the line must contain a ; aswell? What if your source text contains a line like while(_xx==true) { ?

Also, because of

String[] split = get.split("\\s+");
String gvarname = split[0];

your code is not able to split a line like _bb[_ii][_ee] correctly (and even if it would be, because of split[0] you would only replace the first identifier you found, subsequent ones would be ignored). Your split searches for spaces and the source line doesn't contain any. Again, you could probably change this and split for underscores (this would return an array containing bb[ , ii][ and ee] ) and then loop every returned array element until you find the first character that can't be part of your variable identifier (eg until the first non-alphanumeric character).

An _ plus the part of the array element up to that non-alphanumeric character is then the identifier that you want to replace.

Use regex to recognize the entire variable, here using \\b to find word boundaries.

public class Obfuscate {

    private static final Pattern VAR_PATTERN = Pattern.compile("\\b_(\\w+)\\b");
    private final Map<String, String> renames = new HashMap<>();

    public String obfuscate(String sourceCode) {
        StringBuffer buf = new StringBuffer(sourceCode.length() + 100);
        Matcher m = VAR_PATTERN.matcher(sourceCode);
        while (m.find()) {
            String var = m.group(1);
            String newVar = renames.get(var);
            if (newVar == null) {
                newVar = randomVar();
                renames.put(var, newVar);
            }
            m.appendReplacement(buf, newVar);
        }
        m.appendTail(buf);
        return buf.toString();
    }
}

A map is needed to match the same old variable to the same new name.

A Set<String> of new names might be needed to check that the generated name does not repeat.

Your approach of doing a replaceAll of the same var is fine too, but requires reading all. The method above can be repeated (say per line), hence the map as field.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM