Java — правильное форматирование строки с учетом escape-последовательностей и escape-символов

#java #string #escaping

#java #строка #экранирование

Вопрос:

Учитывая новую строку (n), табуляцию (t) и escape-символ как я могу правильно форматировать строку, чтобы она правильно обрабатывала эти escape-последовательности и escape-символы. Пример 1:

 "string \t t"
  

Вывод будет:

 "string t    "
  

Таким образом, в этом случае \t экранируется только в t, а t форматируется с помощью tab

Пример 2:

 "string \t n \n"
  

Вывод:

 "string t
n"
  

Я попробовал решение методом перебора, но оно не сработало, поскольку у меня возникли проблемы с разделением табуляций и пробелов обратной косой чертой.

 String v= "..." //v for value
v = v.replace("\"",""");
v = v.replace("\\","\");
v = v.replace("\t", "  ");
v = v.replace("\n", "n");
v = v.replace("\t", "\t");
v = v.replace("\n", "\n");
  

Если бы я запустил этот код в первом примере, это дало бы:

 "string         "
  

Комментарии:

1. \ является escape для обратной косой черты. n является escape для новой строки. t является escape для символа табуляции. \" является escape для цитаты. Это действительно так просто. Вы говорите, что «пытались найти решение методом перебора» , но не сказали, что пытались решить, так как же вы ожидаете, что мы вам поможем?

2. Вы хотите сказать, что \t хотите, чтобы вас оценивали как [tab] , а не t как?

3. @Andreas \ должен экранировать обратную косую черту, а \t или \n должны экранировать табуляцию или новую строку да

4. @Zircon Я хочу, чтобы \t был буквальным t

5. Итак, вы хотите, чтобы строка, содержащая a , за которой сразу следует a t , обновлялась, чтобы заменить двухсимвольную подстроку t одним символом табуляции ? Если это так, обновите свой вопрос и четко скажите это.

Ответ №1:

похоже, что одна комбинация «грубой силы», которую вы не пробовали, верна

 replace("\t", "t")
  

чтение «замените все комбинации <обратная косая черта> < t > на < tab >»

Соберите их все вместе, чтобы получить

 v = v.replace("\t", "t").replace("\n", "n")
  

(нет необходимости заменять сам по себе)

Ответ №2:

Сначала вы можете заменить экранированные символы, а затем заменить экранированные косые черты одиночными косыми чертами:

 [, , , n] -> [, , n] -> [, n]
  

Мы можем сделать это, найдя вхождения двух пар косых черт:

 (^|[^\])(\\)*

- (^|[^\]) is the start of the string or not a slash
- (\\)* is slash pairs
  

Объедините это с символом, который вы хотите заменить (например n ):

 ((^|[^\])(\\)*)(\n)
  

Затем мы экранируем эту строку для java:

 ((^|[^\\])(\\\\)*)(\\n)
  

Теперь вы можете написать вспомогательный метод для этого регулярного выражения, который сохраняет первую группу $1 и заменяет вторую группу:

 public static String replaceEscapedChar(
    final String source, 
    final char escaped, 
    final char actual
) {
    final String replacee = "(\\"   escaped   ")";
    final String replacement = "$1"   actual;
    return source.replaceAll("((^|[^\\])(\\\\)*)"   replacee, replacement); 
}
  

Например. Следующее производит:

 replaceEscapedChar("Test\\\nTest\\n", 'n', 'n');

Test\
Test\n
  

PS: вы также можете впоследствии удалить кавычки, написав:

 source.replaceAll("((\\\\) )", "\\");