Почему это регулярное выражение Java не работает? - PullRequest
2 голосов
/ 22 апреля 2009

Мне нужно создать регулярное выражение, которое позволяет строке содержать любое количество:

  • буквенно-цифровые символы
  • пространства
  • (
  • )
  • &
  • .

Другие символы запрещены. Я использовал RegexBuddy для создания следующего регулярного выражения, которое работает правильно, когда я тестирую его в RegexBuddy:

\w* *\(*\)*&*\.*

Затем я использовал функцию «Использовать» в RegexBuddy, чтобы преобразовать ее в код Java, но она не работает должным образом при использовании простой тестовой программы:

public class RegexTest
{
  public static void main(String[] args)
  {
    String test = "(AT) & (T)."; // Should be valid
    System.out.println("Test string matches: "
      + test.matches("\\w* *\\(*\\)*&*\\.*")); // Outputs false
  }
}
  • Я должен признать, что у меня есть слабое место, когда дело доходит до регулярных выражений. Кто-нибудь может объяснить, почему это не работает, пожалуйста?

Ответы [ 4 ]

13 голосов
/ 22 апреля 2009

Это регулярное выражение проверяет любое количество пробелов, за которым следует любое количество буквенно-цифровых символов, затем любое количество открытых парен, затем любое количество близких, затем любое количество амперсандов и любое количество периодов. .

То, что вы хотите, это ...

test.matches("[\\w \\(\\)&\\.]*")

Как уже упоминалось mmyers, это позволяет пустую строку. Если вы не хотите разрешить пустую строку ...

test.matches("[\\w \\(\\)&\\.]+")

Хотя это также позволит использовать строку, состоящую только из пробелов или только точек, и т. Д. Если вы хотите указать хотя бы один буквенно-цифровой символ ...

test.matches("[\\w \\(\\)&\\.]*\\w+[\\w \\(\\)&\\.]*")

Таким образом, вы понимаете, что говорит регулярное выражение ... все, что в квадратных скобках ("[]") указывает на набор символов. Итак, где «a *» означает 0 или более символов «a», [abc] * означает 0 или более символов, каждый из которых является символом «a», «b» или «c».

4 голосов
/ 23 апреля 2009

Разница между вашим фрагментом кода Java и вкладкой «Тест» в RegexBuddy заключается в том, что метод match () в Java требует, чтобы регулярное выражение совпадало со всей строкой, а вкладка «Тест» в RegexBuddy допускает частичное совпадение. Если вы используете свое оригинальное регулярное выражение в RegexBuddy, вы увидите несколько блоков желтого и синего выделения. Это указывает на то, что RegexBuddy нашел несколько частичных совпадений в вашей строке. Чтобы получить регулярное выражение, работающее по назначению с match (), его нужно редактировать до тех пор, пока весь объект теста не будет выделен желтым, или если вы выключите подсветку, пока кнопка «Найти сначала» не выделит весь текст.

В качестве альтернативы, вы можете использовать якоря \ A и \ Z в начале и в конце вашего регулярного выражения, чтобы заставить его соответствовать всей строке. Когда вы делаете это, ваш regex всегда ведет себя одинаково, независимо от того, тестируете ли вы его в RegexBuddy или используете ли вы match () или другой метод в Java. Только match () требует полного совпадения строк. Все остальные методы Matcher в Java допускают частичное совпадение.

4 голосов
/ 22 апреля 2009

Может быть, я неправильно понимаю ваше описание, но разве вы не определяете класс символов без порядка, а не конкретной последовательности? Разве ваше регулярное выражение не должно иметь структуру [xxxx] +, где xxxx - это реальные символы, которые вы хотите?

2 голосов
/ 22 апреля 2009

регулярное выражение

\w* *\(*\)*&*\.*

выдаст вам описанные вами предметы, но только в том порядке, в котором вы их описали, и у каждого может быть столько, сколько вам нужно. Так что "skjhsklasdkjgsh ((((()))))) &&&&& ....." работает, но не смешивая символы.

Вы хотите такое регулярное выражение:

\[\w\(\)\&\.]+\

, что позволит смешивать все символы.

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

...