2014-09-18 2 views
4

Я заменить набор подстрок в строку другой подстроки, напримерЗамените набор подстрок в строке более эффективным способом?

  1. "^t" с "\t"
  2. "^=" с "\u2014"
  3. "^+" с "\u2013"
  4. "^s" с "\u00A0"
  5. "^?" с "."
  6. "^#" с "\\d"
  7. "^$" с "[a-zA-Z]"

Итак, я попытался с:

String oppip = "pippo^t^# p^+alt^shefhjkhfjkdgfkagfafdjgbcnbch^"; 

Map<String,String> tokens = new HashMap<String,String>(); 
tokens.put("^t", "\t"); 
tokens.put("^=", "\u2014"); 
tokens.put("^+", "\u2013"); 
tokens.put("^s", "\u00A0"); 
tokens.put("^?", "."); 
tokens.put("^#", "\\d"); 
tokens.put("^$", "[a-zA-Z]"); 

String regexp = "^t|^=|^+|^s|^?|^#|^$"; 

StringBuffer sb = new StringBuffer(); 
Pattern p = Pattern.compile(regexp); 
Matcher m = p.matcher(oppip); 
while (m.find()) 
    m.appendReplacement(sb, tokens.get(m.group())); 
m.appendTail(sb); 
System.out.println(sb.toString()); 

Но это не работает. tokens.get(m.group()) выдает исключение.

Любая идея, почему?

+2

Что делает исключение 'tokens.get (m.group())' бросить? Можете ли вы дать полную трассировку стека исключений? – Unihedron

+1

Извините. Я забыл. Исключение нулевого указателя – Matt3o

ответ

5

В regex ^ означает «начало текста» (или «не» в классе символов как отрицание). Перед ним нужно поместить обратную косую черту, которая становится двумя обратными косыми чертами в строке java.

String regexp = "\\^[t=+s?#$]"; 

Я немного уменьшил его.

6

Вам не обязательно использовать HashMap. Рассмотрите возможность использования простых массивов, а петля:

String oppip = "pippo^t^# p^+alt^shefhjkhfjkdgfkagfafdjgbcnbch^"; 

String[] searchFor = 
{"^t", "^=", "^+", "^s", "^?", "^#", "^$"}, 
     replacement = 
{"\\t", "\\u2014", "\\u2013", "\\u00A0", ".", "\\d", "[a-zA-Z]"}; 

for (int i = 0; i < searchFor.length; i++) 
    oppip = oppip.replace(searchFor[i], replacement[i]); 

// Print the result. 
System.out.println(oppip); 

Вот online code demo.


Для полноты картины можно использовать двумерный массив для подобного подхода:

String oppip = "pippo^t^# p^+alt^shefhjkhfjkdgfkagfafdjgbcnbch^"; 

String[][] tasks = 
{ 
    {"^t", "\\t"}, 
    {"^=", "\\u2014"}, 
    {"^+", "\\u2013"}, 
    {"^s", "\\u00A0"}, 
    {"^?", "."}, 
    {"^#", "\\d"}, 
    {"^$", "[a-zA-Z]"} 
}; 

for (String[] replacement : tasks) 
    oppip = oppip.replace(replacement[0], replacement[1]); 

// Print the result. 
System.out.println(oppip); 
+0

Я думаю, вы имеете в виду 'replaceAll (...)' not 'replace (...)', но в остальном мне нравится это решение. Не пытайтесь делать все замены сразу, делайте их по одному, а код намного проще. –

+3

@IanMcLaird '.replaceAll' принимает регулярное выражение. ['.replace()' принимает строку и ее литерал] (http://stackoverflow.com/a/25365703/3622940), поэтому нет необходимости в экранировании. – Unihedron

+2

@IanMcLaird 'replaceAll' использует регулярное выражение, в то время как OP явно хочет заменить литералы, поэтому« замена »здесь лучше. Но есть возможная проблема, если циклические замены могут существовать как 'a-> b'' b-> a'. В этом случае, заменив все 'a' на' b', тогда все 'b' с' a' мы получим только 'a'.'appendReplacement' и' appendTail' решает эту проблему. – Pshemo

Смежные вопросы