Разделить строку Java с помощью '\r\n', '\r' или '\n' и сохранить ее с предшествующей подстрокой

Моя входная строка содержит разделители строк смешанного типа, включая '\r\n', '\r' или '\n'. Я хочу разделить строку и сохранить разделитель строк с предшествующей ему подстрокой. Я следил за двумя сообщениями ниже

Как разделить строку, но сохранить разделители?

Разделить строку Java по новой строке

и придумать что-то вроде:

String input = "1 dog \r\n 2 cat";
String[] output = input.split( "(?<=((\\r\\n)|\\r|\\n))")));

выход ["1 dog\r", "\n", " 2 cat"], однако желаемый результат ["1 dog\r\n", " 2 cat"].

Если я изменю ввод на String input = "1 dog \r 2 cat"; или String input = "1 dog \n 2 cat";, мой код может выдать желаемый результат. Пожалуйста, порекомендуйте. Заранее спасибо.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
0
658
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если вы используете следующее регулярное выражение:(?<=\\r\\n|\\r(?!\\n)|\\n) для разделения строки, оно будет работать, как задумано.

Что происходит с вашим регулярным выражением, так это то, что когда встречается \r\n, утверждение просмотра назад будет истинным (?<=\r), и оно разделит строку сразу после \r.

Вот почему я добавил отрицательный прогноз (?!\n) после \r, чтобы убедиться, что символ после \r не является \n. Это предотвратит раскол между \r и \n и сохранит его в целом.

Демонстрация: https://regex101.com/r/H6PNmY/1/ (где я заменил \r на a и \n на b для удобочитаемости)

Когда вы вернете это в свой код:

String input = "1 dog \r\n 2 cat, 1 car \r 2 planes, 1 apple \n 2 peaches";
String[] output = input.split("(?<=\\r\\n|\\r(?!\\n)|\\n)");

for(int i=0; i<output.length; i++)
{
  printASCII(output[i]);
  System.out.println("== = ");        
}

с printASCII определяется как:

public static void printASCII(String in)
{
    for(int i=0; i<in.length(); i++)
        System.out.println("The ASCII value of " + in.charAt(i) + "  =  " + (int)in.charAt(i) );
}

Это дает вам следующий вывод:

The ASCII value of 1  =  49
The ASCII value of    =  32
The ASCII value of d  =  100
The ASCII value of o  =  111
The ASCII value of g  =  103
The ASCII value of    =  32
The ASCII value of 
  =  13
The ASCII value of 
  =  10
===
The ASCII value of    =  32
The ASCII value of 2  =  50
The ASCII value of    =  32
The ASCII value of c  =  99
The ASCII value of a  =  97
The ASCII value of t  =  116
The ASCII value of ,  =  44
The ASCII value of    =  32
The ASCII value of 1  =  49
The ASCII value of    =  32
The ASCII value of c  =  99
The ASCII value of a  =  97
The ASCII value of r  =  114
The ASCII value of    =  32
The ASCII value of 
  =  13
===
The ASCII value of    =  32
The ASCII value of 2  =  50
The ASCII value of    =  32
The ASCII value of p  =  112
The ASCII value of l  =  108
The ASCII value of a  =  97
The ASCII value of n  =  110
The ASCII value of e  =  101
The ASCII value of s  =  115
The ASCII value of ,  =  44
The ASCII value of    =  32
The ASCII value of 1  =  49
The ASCII value of    =  32
The ASCII value of a  =  97
The ASCII value of p  =  112
The ASCII value of p  =  112
The ASCII value of l  =  108
The ASCII value of e  =  101
The ASCII value of    =  32
The ASCII value of 
  =  10
===
The ASCII value of    =  32
The ASCII value of 2  =  50
The ASCII value of    =  32
The ASCII value of p  =  112
The ASCII value of e  =  101
The ASCII value of a  =  97
The ASCII value of c  =  99
The ASCII value of h  =  104
The ASCII value of e  =  101
The ASCII value of s  =  115
===

Это показывает, что символы EOL правильно хранятся, как вы просили.

ASCII table:https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.networkcomm/conversion_table.htm

Ответ принят как подходящий

Вы получаете свой результат ["1 dog\r", "\n", " 2 cat"], потому что в вашем шаблоне используется чередование, которое будет соответствовать либо (\r\n), либо \r, либо \n.

Когда в строке примера встречается \r\n, утверждение ретроспективного просмотра будет истинным после \r и впервые разделится.

Тогда обратное утверждение будет истинным после \n и разделится во второй раз.

Что вы можете сделать, так это использовать \R в положительном взгляде назад, чтобы утверждать, что слева есть последовательность новой строки юникода:

String input = "1 dog \r\n 2 cat";
String[] output = input.split("(?<=\\R)");

Демонстрация Java

Другой вариант исправить ваше регулярное выражение — сделать его атомная группа:

(?<=(?>\\r\\n|\\r|\\n))

Демонстрация Java

При чтении эта почта, когда \r сопоставляется в ретроспективном просмотре с использованием атомарной группы, следующий \n также сопоставляется.

Очень хороший ответ! Использование \R лучше моего решения! +1

Allan 08.04.2019 08:40

Я думаю, что этот ответ будет выглядеть лучше, если вы объясните причину, по которой регулярное выражение OP не сработало.

Wiktor Stribiżew 08.04.2019 09:24

@ Аллан, спасибо, я повторно использовал часть вашего printASCII в демонстрации Java, чтобы перечислить символы, если вы согласны.

The fourth bird 08.04.2019 10:09

@WiktorStribiżew Это справедливо, я добавил объяснение регулярного выражения OP.

The fourth bird 08.04.2019 10:10

Да, но почему \R работает, вероятно, более интересно, и ответ на вопрос, почему \R работает, также покажет OP, как исправить их регулярное выражение.

Wiktor Stribiżew 08.04.2019 10:16

@Thefourthbird: вперед! ;-)

Allan 08.04.2019 10:33

Другие вопросы по теме