Java regex экранированные символы

2

При сопоставлении определенных символов (например, строки) вы можете использовать регулярное выражение "\\n" или просто "\n". Например, следующее разбиение строки на массив строк:

String[] lines = allContent.split("\\r?\\n");

Но следующее работает так же хорошо:

String[] lines = allContent.split("\r?\n");

Мой вопрос:

Выполняете ли эти два действия точно так же, или есть какая-то тонкая разница? Если последнее, можете ли вы привести примерный случай, когда вы получите разные результаты?

Или существует ли разница только в [возможной/теоретической] производительности?

  • 2
    Нет никакой разницы. \\n соответствует LF, \n соответствует LF.
  • 2
    Если вы используете режим КОММЕНТАРИИ, разница должна быть.
Показать ещё 2 комментария
Теги:

2 ответа

2
Лучший ответ

В текущем сценарии нет никакой разницы. Обычные последовательности escape-последовательности строки формируются с помощью одного обратного слэша, а затем действительный escape-символ ("\n", "\r" и т.д.), А управляющие последовательности регулярных выражений формируются с помощью буквальной обратной косой черты (то есть, двойная обратная косая черта в строковом литерале Java) и действительный символ escape regex ("\\n", "\\d" и т.д.).

"\n" (escape-последовательность) - это буквальная LF (новая строка), а "\\n" - это escape-последовательность регулярного выражения, которая соответствует символу LF.

"\r" (escape-последовательность) представляет собой литерал CR (возврат каретки), а "\\r" - последовательность escape-выражений регулярного выражения, которая соответствует символу CR.

"\t" (escape-последовательность) является символом символа табуляции, а "\\t" является управляющей последовательностью регулярного выражения, которая соответствует символу табуляции.

См. Список в документах Java regex для поддерживаемого списка экранов регулярных выражений.

Тем не менее, если вы используете флаг Pattern.COMMENTS (используется для представления комментариев и форматирования рисунка красиво, заставляя механизм регулярных выражений игнорировать все незаметные пробелы в шаблоне), вам нужно либо использовать "\\n" либо "\\\n" для определения новой строки (LF) в строковом литерале Java и "\\r" или "\\\r" для определения возврата каретки (CR).

См. Тест Java:

String s = "\n";
System.out.println(s.replaceAll("\n", "LF")); // => LF
System.out.println(s.replaceAll("\\n", "LF")); // => LF
System.out.println(s.replaceAll("(?x)\\n", "LF")); // => LF
System.out.println(s.replaceAll("(?x)\\\n", "LF")); // => LF
System.out.println(s.replaceAll("(?x)\n", "<LF>")); 
// => <LF>
//<LF>

Почему последний производит <LF> + новую строку + <LF>? Поскольку "(?x)\n" равно "", пустой шаблон, и он соответствует пустому пространству перед новой строкой и после него.

0

Да, есть разные. Компилятор Java имеет другое поведение для Unicode Escapes в разделе Java Book The Java Language Specification section 3.3;

Язык программирования Java определяет стандартный способ преобразования программа, написанная в Unicode в ASCII, которая изменяет программу на форма, которая может обрабатываться инструментами на основе ASCII. Преобразование включает в себя преобразование любых экранов Unicode в исходный текст программы в ASCII, добавив дополнительный u - например, \uxxxx становится \ uuxxxx - при одновременном преобразовании несимвольных символов в исходный текст для экранов Unicode, содержащих один u каждый.

Итак, как это влияет на / n vs //n в Java Doc:

Поэтому необходимо удвоить обратную косую черту в строковых литералах которые представляют собой регулярные выражения для защиты их от интерпретации с помощью компилятора байт-кода Java.

Пример одного документа:

Строковый литерал "\ b", например, соответствует одному обратному пространству символ, интерпретируемый как регулярное выражение, тогда как "\ b" соответствует границе слова. Строковый литерал "(привет)" является незаконным и приводит к ошибке времени компиляции; чтобы соответствовать строке (привет) необходимо использовать строковый литерал "\ (hello \)".

  • 1
    Вы объясняете необходимость использования "\\" для определения одиночной обратной косой черты в строковых литералах Java. Вопрос OP заключается в том, совпадают ли "\n" и "\\n" одинаковые строки. Хотя шаблоны отличаются, они соответствуют одному и тому же тексту. Вот почему я говорю, что в текущем сценарии нет никакой разницы .
  • 0
    Да, ваш ответ правильный, я просто хотел разницу между ними. В некоторых сценариях есть разные результаты, а в других сценариях - те же самые результаты.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню