Как мне сделать это регулярное выражение более общим, иногда это работает, а иногда нет - PullRequest
0 голосов
/ 26 июня 2009

У меня есть следующее регулярное выражение, которое я использую в Java-приложении. Иногда это работает правильно, а иногда нет.

<!-- <editable name=(\".*\")?> -->(.*)<!-- </editable> -->

Иногда у меня будут пробелы до / после него, иногда будет текст. То же самое касается региона в тегах.

Основная проблема в том, что name = (\ ". * \")?> Иногда соответствует больше, чем это должно быть Я не уверен, что это что-то, что можно решить, просто взглянув на этот код.

Ответы [ 4 ]

5 голосов
/ 26 июня 2009

XML не является обычным языком, равно как HTML или любой другой язык с "вложенными" конструкциями Не пытайтесь анализировать его с помощью регулярных выражений.

Выберите парсер XML .

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

Как уже отмечали другие, жадный .* (точка-звезда), который соответствует атрибуту "name", должен быть сделан не жадным (.*?) или даже лучше, заменен классом отрицанных символов ([^"]*), поэтому он не может совпадать после заключительной кавычки, независимо от того, что происходит в остальной части регулярного выражения. Как только вы исправите это, вы, вероятно, обнаружите, что у вас есть такая же проблема с другой точкой-звездой; вам тоже нужно сделать его не жадным.

Pattern p = Pattern.compile(
    "<!--\\s*<editable\\s+name=\"([^\"]*)\">\\s*-->" +
    "(.*?)" +
    "<!--\\s*</editable>\\s*-->",
    Pattern.DOTALL);

Я не понимаю значение ваших замечаний по поводу пробелов. Если речь идет о переводах строки и / или возврате каретки, модификатор DOTALL позволяет точкам соответствовать этим точкам - и, конечно, \s также соответствует им.

Я написал это в форме строкового литерала Java, чтобы избежать путаницы в том, где вам нужно указывать обратную косую черту и сколько их нужно. В «сыром» регулярном выражении в каждой из пробелов (\s*) будет только один обратный слеш, и кавычки не нужно будет экранировать ("[^"]*").

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

Я бы заменил это .* на [\w-]*, например, если имя является идентификатором какого-либо рода.

или [^\"]*, чтобы не захватывать двойные кавычки в конце.

Edit:

Как уже упоминалось в другом посте, вы можете рассмотреть возможность простого обхода DOM, процесса оценки на основе XPath или XQuery вместо простого регулярного выражения. Но учтите, что вам все равно понадобится регулярное выражение в процессе фильтрации, потому что вы можете найти целевые комментарии только проверяя их тело по регулярному выражению (так как я сомневаюсь, что тело является постоянным, исходя из примера).

Редактировать 2:

Может случиться так, что начальные, конечные или внутренние пробелы в теле комментария приведут к неудаче вашего регулярного выражения. Попробуйте поставить \s* в начале и в конце, плюс \s+ перед атрибутом, похожим на атрибут.

<!--\s*<editable\s+name=(\"[^\"]*\")?>\s*-->(.*)<!--\s*</editable>\s*-->

Или при фильтрации по XML-поиску:

"\\s*<editable\\s+name=(\"[^\"]*\")?>\\s*"
"\\s*</editable>\\s*"

Редактировать 3: Исправлены побеги дважды. Спасибо Алан М .

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

множитель * по умолчанию «жадный», что означает, что он соответствует максимально возможному количеству, но при этом сопоставляется с шаблоном успешно.

Вы можете отключить это с помощью * ?, поэтому попробуйте:

(\".*?\")
...