Java - как сопоставить регулярное выражение, содержащее одинарные кавычки? - PullRequest
1 голос
/ 07 июня 2009

[ИЗМЕНЕНО - действительно извините, код, который я цитировал, был неправильным - изменил сообщение ниже, чтобы отразить это. Извиняюсь! Спасибо за ваше терпение.]

Я новичок в регулярных выражениях и хочу сопоставить шаблон в Java (следуя этому решению - Строка Java - получить все между (но не включая) двумя регулярными выражениями? ).

Строка [РЕДАКТИРОВАННАЯ]:

<row><column name='_id'>1</column></row><row><column name='text'>Header\n\n\ntext</column></row><row><column name='pwd'>password</column></row>

И я хочу вернуть только то, что находится между тегами имя столбца = 'текст' , поэтому:

Header\n\n\ntext

У меня есть код ниже [ИЗМЕНЕНО], но он не совпадает. Любые идеи о том, как мне нужно изменить шаблон?

Спасибо!

package test;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Regex {

    public static void main(String[] args) {
        Pattern p = Pattern.compile(
                "<row><column name='text'>(.*)</column></row>",
                Pattern.DOTALL
            );
        Matcher matcher = p.matcher(
                "<row><column name='_id'>1</column></row><row><column name='text'>Header\n\n\ntext</column></row><row><column name='pwd'>password</column></row>"
            );
        if(matcher.matches()){
                System.out.println(matcher.group(1));
        }
    }
}

Ответы [ 4 ]

4 голосов
/ 07 июня 2009

Отправленный вами (неотредактированный) код отлично работает ... он соответствует и распечатывает ожидаемое сообщение.

Отредактированный код не работает, однако если вы слегка измените регулярное выражение, чтобы оно выглядело так:

Pattern p = Pattern.compile(
            ".*<row><column name='text'>(.*)</column></row>.*",
            Pattern.DOTALL
        );

вы получите совпадение:

Header


text</column></row><row><column name='pwd'>password

Это, вероятно, не то, что вы на самом деле хотите, так что вам нужно будет еще более усовершенствовать регулярное выражение. Использование регулярных выражений для обработки разбора xml / html, как правило, не очень хороший подход. Предложение Ишая использовать синтаксический анализатор XML - лучший способ сделать это, иначе вы, скорее всего, получите чрезвычайно сложное и негибкое регулярное выражение.

3 голосов
/ 07 июня 2009

Возможно, вы действительно хотите получить это:

public static void main(String[] args) {
    Pattern p = Pattern.compile(
            "<row><column name='(.*?)'>(.*?)</column></row>",
            Pattern.DOTALL
        );

    Matcher matcher = p.matcher(
            "<row><column name='text'>Header\n\n\ntext</column></row>"
        );

    if(matcher.matches()){
            System.out.println(matcher.group(2));
    }
}

Потому что в вашем реальном примере в имени = значении может быть что угодно (по крайней мере, в реальном мире это будет казаться намного больше).

При этом, если это становится намного более нетривиальным, вы можете захотеть смотреть на это как на SAX-парсер (встроенный в JDK 1.5+, так что это не обязательно проблема зависимости от библиотеки). Regex - лучший способ разбора XML, если вы действительно не заботитесь о структуре документа и просто хотите извлечь из него что-то тривиальное. Однако, если вы начнете разбираться с атрибутами и заботиться о том, что они есть в XML, продолжение маршрута regex приведет к переизобретению колеса.

1 голос
/ 07 июня 2009

Попробуйте сопоставить (.*?) вместо (.*).

(.*) - это жадный поиск, который будет соответствовать всему после него.

(.*?) остановится при первом появлении "</column></row>".

Редактировать: Это на самом деле не должно влиять на ваш пример, но если в строке есть еще один "</column></row>", тогда ваш шаблон не будет соответствовать ожидаемому.

0 голосов
/ 08 июня 2009

Ваша проблема не имеет ничего общего с символами кавычек. Вам просто нужно переключиться на негладкий квантификатор (как предлагали другие) и использовать метод find() вместо matches():

public static void main(String[] args)
{
  Pattern p = Pattern.compile(
      "<row><column name='text'>(.*?)</column></row>",
      Pattern.DOTALL
  );

  Matcher matcher = p.matcher(
      "<row><column name='_id'>1</column></row>" +
      "<row><column name='text'>Header\n\n\ntext</column></row>" +
      "<row><column name='pwd'>password</column></row>"
  );

  if(matcher.find()) {
      System.out.println(matcher.group(1));
  }
}

matches() возвращает true только в том случае, если регулярное выражение совпадает с самого начала целевой строки до самого конца. Если вы хотите сопоставить что-либо меньше, чем целая строка, вам нужно использовать find().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...