Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Нежадный паттерн с флагом DOTALL


Автор: Antropoid 2.12.2010, 00:08
Помогите, плиз с паттерном.

Текст: 
\n\nPar1\n\nPar2\n\nPar3
Ожидаемый результат: 
\n\nPar1
\n\nPar2
\n\nPar3

Текст: 
\n\nPar1\nPar2\n\nPar3
Ожидаемый результат: 
\n\nPar1\nPar2
\n\nPar3

Первый пример работает с таким вот паттерном
Код

Pattern p = Pattern.compile("\n[ \t\f\r]*\n.*");

второй - нет.
Вычитал, что дело в точке(.), \n не считается точкой, чтобы считалось нужно взводить флаг Pattern.DOTALL. Пробовал с флагом - не получается  smile 

Как тут быть?

Автор: aleksandy 2.12.2010, 09:06
Код
private static String escape(String s) {
    StringBuilder sout = new StringBuilder();
    for (int i = 0, len = s.length(); i < len; i ++) {
        char ch = s.charAt(i);
        if (ch == '\n') {
            sout.append("\\n");
        } else {
            sout.append(ch);
        }
    }
    return sout.toString();
}

public static void main(String[] args) throws Exception {
    String s = "\n\nPar1\n\nPar2\n\nPar3";
    Matcher m = Pattern.compile("(\\n{2}(?:[^\\n]|\\n(?!\\n))*)").matcher(s);
    System.out.println("=== " + escape(s) + " ===");
    while (m.find()) {
        System.out.println(escape(m.group(1)));
    }
    s = "\n\nPar1\nPar2\n\nPar3";
    m.reset(s);
    System.out.println("=== " + escape(s) + " ===");
    while (m.find()) {
        System.out.println(escape(m.group(1)));
    }
}

Автор: Antropoid 2.12.2010, 13:11
Спасибо за ответ, но к сожалению он не подходит.

Я явно не сказал, но есть еще условие - между \n и \n могут быть whitespaces-символы кроме \n. 
Я это обозначил так:
Код

Pattern p = Pattern.compile("\n[ \t\f\r]*\n.*");

А ваш вариант заточен под невозможность появления \n\n в конце найденной группы.

Автор: aleksandy 2.12.2010, 13:47
Тогда сначала
Код

s = s.replaceAll("\\n\\s+\\n", "\n\n");

а потом как я показал.

Автор: Kircul 2.12.2010, 13:53
Может как нибудь так?
Код

Pattern p = Pattern.compile("(\n[ \t\f\r]*\n.*?)((\n[ \t\f\r]*\n)|$)", Pattern.DOTALL);
Matcher m = p.matcher("\n\nPar1\nPar2\n\nPar3");
int st = 0;
while (m.find(st)) {
    st = m.end(1);
    System.out.println("find >>>" + m.group(1) + "<<<");
}

Автор: Antropoid 2.12.2010, 14:51
aleksandy, +1
Kircul, +1 
Сенкс! Оба примера работают!

Автор: aleksandy 3.12.2010, 09:05
Antropoid,  я тут еще немного на досуге поразмышлял и вот что у меня полчилось:
В моем примере надо поменять 16 строку на вот такую
Код
Matcher m = Pattern.compile("\\n\\s*\\n(([^\\n]|\\n(?!\\s*\\n))*)").matcher(s);

А  19  и 25 - на такую 
Код
System.out.println(escape("\n\n" + m.group(1)));


Так будет эффективней.

Автор: Antropoid 3.12.2010, 15:59
aleksandy, сенкс!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)