вот мое решение:
// can extract annotation and text-inside-parentheses
private static final String REGEX = "@(\\w+)\\((.+)\\)";
//Read File
List<String> lines = Files.readAllLines(Paths.get(filename));
//Create a pattern to find for
Pattern pattern = Pattern.compile(REGEX);
// extractor function uses pattern's second group (text-within-parentheses)
Function<String, String> extractOnlyTextWithinParentheses = s -> {
Matcher m = pattern.matcher(s);
m.find();
return m.group(2);
};
// all lines are filtered and text will be extracted using extractor-fn
Stream<String> streamOfExtracted = lines.stream()
.filter(pattern.asPredicate())
.map(extractOnlyTextWithinParentheses);
//Perform desired operation
streamOfExtracted.forEach(System.out::println);
Объяснение:
Давайте сначала выясним, что должен делать используемый шаблон регулярного выражения @(\\w+)\\((.+)\\)
:
ПРИНЯТЬ:Вы фильтруете текст для Java-подобной аннотации, такой как @MyPattern
, совпадающей с конкретными строками, используя регулярное выражение
@\\w+
соответствует символу at, за которым следует слово(\\w
имеет специальное значение и обозначает слово, то есть буквенные буквы и подчеркивания).Таким образом, он будет соответствовать любой аннотации (например, @Trace
, @User
и т. Д.). \\(.+\\)
соответствует некоторому тексту в скобках (например, * 1028).*, где скобки тоже должны быть экранированы \\(
и \\)
и .+
для любого непустого текста внутри
Примечание: неэкранированные скобки имеют особое значение внутри любого регулярного выражения, то есть группировка и захват
Соответствующие скобки и извлечение их содержимого см. в этом ответе на Шаблон для извлечения текста в скобках .
извлечение текста с использованием групп захвата внутри регулярного выражения
Просто используйте круглые скобки (без экранирования), чтобы сформировать группу, и запомните их номер заказа. (grouped)(Regex)
будет соответствовать тексту groupedRegex
и может извлечь две группы:
- группа № 1:
grouped
- группа № 2:
Regex
Чтобы получить эти группы, используйте matcher.find()
, а затем matcher.group()
или его перегруженные методы.
опция для проверки регулярного выражения и извлечения
В IntelliJ вы можете использовать действие Проверить RegExp в IntelliJ: ALT + Введите в выбранном регулярном выражении, чтобы проверить и адаптировать его.Похоже есть довольно много сайтов для проверки регулярных выражений.Например, http://www.regExPlanet.com также поддерживает синтаксис Java-RegEx, и вы можете проверить извлеченные группы в режиме онлайн.См. пример на RegexPlanet .
Примечание: есть одно особое значение каретки, кроме начало , как Оле ответил выше : это[^)]+
означает совпадение с чем угодно (не менее 1 символа) , кроме закрывающих скобок
делает его расширяемым с помощью функции экстрактора
Если вы замените экстракт-Функция, используемая в качестве аргумента для .map(..)
выше, следуя которой вы также можете напечатать аннотацию-имя и текст внутри скобок (разделенные табуляцией):
Function<String, String> extractAnnotationAndTextWithinParentheses = s -> {
Matcher m = pattern.matcher(s);
m.find();
StringBuilder sb = new StringBuilder();
int lastGroup = m.groupCount();
for (int i = 1; i <= lastGroup; i++) {
sb.append(m.group(i));
if (i < lastGroup) sb.append("\t");
}
return sb.toString();
};
Сводка:
Ваша потоковая передача была эффективной .Ваше регулярное выражение содержало ошибку :
- оно почти совпало с постоянной аннотацией, а именно:
@MyPattern
- вы пытались получить исправление с помощью скобок
- в вашем регулярном выражении была синтаксическая ошибка или опечатка, каретка
^
- не использовала экранированные скобки
\\(
и \\)
вы бы получили не только текст-внутри, а также скобки как экстракт