Разделение Java ест моих персонажей

У меня есть строка, подобная этой String str = "la$le\\$li$lo".

Я хочу разбить его, чтобы получить следующий вывод "la","le\\$li","lo".\$Является $escaped, поэтому он должен быть оставлен на выходе.

Но когда я делаю str.split("[^\\\\]\\$") y, получаем "l","le\\$l","lo".

Из того, что я получаю, мое регулярное выражение сопоставляет $и я $и затем удаляет. Любая идея о том, как вернуть моих персонажей?

Спасибо

Ответ 1

Используйте утверждения соответствия нулевой ширины:

    String str = "la$le\\$li$lo";
    System.out.println(java.util.Arrays.toString(
        str.split("(?<!\\\\)\\$")
    )); // prints "[la, le\$li, lo]"

Регулярное выражение по существу

(?<!\\)\$

Он использует отрицательный lookbehind, чтобы утверждать, что не существует предшествующего \.

См. также


Дополнительные примеры разбиения на утверждения

Простое расщепление предложения, сохранение знаков препинания:

    String str = "Really?Wow!This.Is.Awesome!";
    System.out.println(java.util.Arrays.toString(
        str.split("(?<=[.!?])")
    )); // prints "[Really?, Wow!, This., Is., Awesome!]"

Разделив длинную строку на части фиксированной длины, используя \G

    String str = "012345678901234567890";
    System.out.println(java.util.Arrays.toString(
        str.split("(?<=\\G.{4})")
    )); // prints "[0123, 4567, 8901, 2345, 6789, 0]"

Использование комбинации lookbehind/lookahead:

    String str = "HelloThereHowAreYou";
    System.out.println(java.util.Arrays.toString(
        str.split("(?<=[a-z])(?=[A-Z])")
    )); // prints "[Hello, There, How, Are, You]"

Связанные вопросы

Ответ 2

Причина, по которой удаляются $и я $, заключается в том, что regexp [^\\]\$ соответствует любому символу, который не '\', за которым следует '$'. Вы должны использовать утверждения нулевой ширины

Это та самая проблема, с которой люди пытаются найти q, за которым не следует u.

Первый разрез в правильном регулярном выражении /(?<!\\)\$/ ("(?<!\\\\)\\$" в java)

class Test {
 public static void main(String[] args) {
  String regexp = "(?<!\\\\)\\$";
  System.out.println( java.util.Arrays.toString( "1a$1e\\$li$lo".split(regexp) ) );
 }
}

Урожайность:
[1a, 1e\$li, lo]

Ответ 3

Вы можете попробовать сначала заменить "\ $" на другую строку, такую ​​как кодировка URL для $( "% 24" ), а затем расщепить:

String splits[] = str.replace("\$","%24").split("[^\\\\]\\$");
for(String str : splits){
   str = str.replace("%24","\$");
}

В более общем случае, если str построена чем-то вроде

str = a + "$" + b + "$" + c

Затем вы можете URLEncode a, b и c перед добавлением их вместе

import java.net.URLEncoder.encode;
...
str = encode(a) + "$" + encode(b) + "$" + encode(c)

Ответ 4

import java.util.regex.*;
public class Test {
    public static void main(String... args) {
        String str = "la$le\\$li$lo";
        Pattern p = Pattern.compile("(.+?)([^\\\\]\\$)");
        Matcher m = p.matcher(str);
        while (m.find()) {
            System.out.println(m.group(1));
            System.out.println(m.group(2));
        }
    }
}

дает

l
a$
le\$l
i$