Совпадение совпадений java regex
Скажем, у меня есть файл, и файл содержит следующее:
HelloxxxHelloxxxHello
Я скомпилирую шаблон для поиска 'Hello'
Pattern pattern = Pattern.compile("Hello");
Затем я использую входной поток для чтения в файле и преобразовываю его в String, чтобы он мог быть regexed.
Как только совпад находит совпадение в файле, он указывает это, но он не говорит мне, сколько совпадений найдено; просто, что он нашел совпадение внутри строки.
Итак, поскольку строка относительно короткая, а буфер, который я использую, составляет 200 байт, он должен найти три совпадения. Однако он просто говорит совпадение и не дает мне подсчета количества совпадений.
Самый простой способ подсчета количества совпадений, которые произошли в String. Я пробовал различные для циклов и использовал matcher.groupCount(), но я не получаю никуда быстро.
Ответы
Ответ 1
matcher.find()
не находит все совпадения, только следующее совпадение.
Вам нужно будет сделать следующее:
int count = 0;
while (matcher.find())
count++;
Кстати, matcher.groupCount()
- это нечто совершенно другое.
Полный пример:
import java.util.regex.*;
class Test {
public static void main(String[] args) {
String hello = "HelloxxxHelloxxxHello";
Pattern pattern = Pattern.compile("Hello");
Matcher matcher = pattern.matcher(hello);
int count = 0;
while (matcher.find())
count++;
System.out.println(count); // prints 3
}
}
Обработка совпадений матчей
При подсчете совпадений aa
в aaaa
приведенный выше фрагмент даст вам 2.
aaaa
aa
aa
Чтобы получить 3 совпадения, то есть это поведение:
aaaa
aa
aa
aa
Вы должны искать совпадение по индексу <start of last match> + 1
следующим образом:
String hello = "aaaa";
Pattern pattern = Pattern.compile("aa");
Matcher matcher = pattern.matcher(hello);
int count = 0;
int i = 0;
while (matcher.find(i)) {
count++;
i = matcher.start() + 1;
}
System.out.println(count); // prints 3
Ответ 2
Это должно работать для совпадений, которые могут перекрываться:
public static void main(String[] args) {
String input = "aaaaaaaa";
String regex = "aa";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
int from = 0;
int count = 0;
while(matcher.find(from)) {
count++;
from = matcher.start() + 1;
}
System.out.println(count);
}
Ответ 3
Если вы хотите использовать потоки Java 8 и имеете аллергию на циклы while
, вы можете попробовать это:
public static int countPattern(String references, Pattern referencePattern) {
Matcher matcher = referencePattern.matcher(references);
return Stream.iterate(0, i -> i + 1)
.filter(i -> !matcher.find())
.findFirst()
.get();
}
Отказ от ответственности: это работает только для непересекающихся матчей.
Пример:
public static void main(String[] args) throws ParseException {
Pattern referencePattern = Pattern.compile("PASSENGER:\\d+");
System.out.println(countPattern("[ \"PASSENGER:1\", \"PASSENGER:2\", \"AIR:1\", \"AIR:2\", \"FOP:2\" ]", referencePattern));
System.out.println(countPattern("[ \"AIR:1\", \"AIR:2\", \"FOP:2\" ]", referencePattern));
System.out.println(countPattern("[ \"AIR:1\", \"AIR:2\", \"FOP:2\", \"PASSENGER:1\" ]", referencePattern));
System.out.println(countPattern("[ ]", referencePattern));
}
Это распечатывает:
2
0
1
0
Это решение для несвязанных совпадений с потоками:
public static int countPattern(String references, Pattern referencePattern) {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
new Iterator<Integer>() {
Matcher matcher = referencePattern.matcher(references);
int from = 0;
@Override
public boolean hasNext() {
return matcher.find(from);
}
@Override
public Integer next() {
from = matcher.start() + 1;
return 1;
}
},
Spliterator.IMMUTABLE), false).reduce(0, (a, c) -> a + c);
}
Ответ 4
Это может помочь:
public static void main(String[] args) {
String hello = "HelloxxxHelloxxxHello";
String []matches = hello.split("Hello");
System.out.println(matches.length); // prints 3
}
Ответ 5
Используйте приведенный ниже код, чтобы найти количество совпадений, найденных регулярным выражением в ваших входных данных
Pattern p = Pattern.compile(regex, Pattern.MULTILINE | Pattern.DOTALL);// "regex" here indicates your predefined regex.
Matcher m = p.matcher(pattern); // "pattern" indicates your string to match the pattern against with
boolean b = m.matches();
if(b)
count++;
while (m.find())
count++;
Это обобщенный, а не специфический код, адаптируйте его под свои нужды
Пожалуйста, не стесняйтесь исправлять меня, если есть какая-либо ошибка.