Couchbase xdcr regex - Как исключить ключи с помощью regex?
Я пытаюсь исключить передачу определенных документов в ES с использованием XDCR. У меня есть следующее регулярное выражение, которое фильтрует ABCD и IJ
https://regex101.com/r/gI6sN8/11
Теперь я хочу использовать это регулярное выражение в фильтрации XDCR
^ (?!.(ABCD | IJ)).$
Как исключить ключи с помощью регулярных выражений?
РЕДАКТИРОВАТЬ:
Что делать, если я хочу выбрать все, что не содержит ABCDE и ABCHIJ.
Я старался
2 ответа
Надеюсь, однажды будет встроена поддержка инвертирования выражения соответствия. А пока вот программа на Java 8, которая генерирует регулярные выражения для инвертированного сопоставления префиксов с использованием базовых функций регулярных выражений, поддерживаемых фильтром Couchbase XDCR.
Это должно работать до тех пор, пока ваши префиксы ключей каким-то образом отделены от остальной части ключа. Обязательно включите разделитель во входные данные при изменении этого кода.
Пример вывода для red:
, reef:
, green:
является:
^([^rg]|r[^e]|g[^r]|re[^de]|gr[^e]|red[^:]|ree[^f]|gre[^e]|reef[^:]|gree[^n]|green[^:])
Файл: NegativeLookaheadCheater.java
import java.util.*;
import java.util.stream.Collectors;
public class NegativeLookaheadCheater {
public static void main(String[] args) {
List<String> input = Arrays.asList("red:", "reef:", "green:");
System.out.println("^" + invertMatch(input));
}
private static String invertMatch(Collection<String> literals) {
int maxLength = literals.stream().mapToInt(String::length).max().orElse(0);
List<String> terms = new ArrayList<>();
for (int i = 0; i < maxLength; i++) {
terms.addAll(terms(literals, i));
}
return "(" + String.join("|", terms) + ")";
}
private static List<String> terms(Collection<String> words, int index) {
List<String> result = new ArrayList<>();
Map<String, Set<Character>> prefixToNextLetter = new LinkedHashMap<>();
for (String word : words) {
if (word.length() > index) {
String prefix = word.substring(0, index);
prefixToNextLetter.computeIfAbsent(prefix, key -> new LinkedHashSet<>()).add(word.charAt(index));
}
}
prefixToNextLetter.forEach((literalPrefix, charsToNegate) -> {
result.add(literalPrefix + "[^" + join(charsToNegate) + "]");
});
return result;
}
private static String join(Collection<Character> collection) {
return collection.stream().map(c -> Character.toString(c)).collect(Collectors.joining());
}
}
редактировать:
Извините, после дальнейшего изучения этот метод недействителен. Например, [^B] позволяет A обойтись, пропуская AABCD (поскольку сначала он будет соответствовать AA, а затем - BCD с [^A]. Пожалуйста, не обращайте внимания на этот пост.
Демо здесь показывает, что метод ниже недействителен
(игнорировать это)
Вы можете использовать трюк в стиле posix, чтобы исключить слова.
Ниже следует исключить ABCD
а также IJ
,
Вы получаете представление о шаблоне из этого.
По сути, вы помещаете все первые буквы в отрицательный класс
как первый в списке чередования, затем обрабатывать каждое слово
в отдельном чередовании.
^(?:[^AI]+|(?:A(?:[^B]|$)|AB(?:[^C]|$)|ABC(?:[^D]|$))|(?:I(?:[^J]|$)))+$
расширенный
^
(?:
[^AI]+
|
(?: # Handle 'ABCD`
A
(?: [^B] | $ )
| AB
(?: [^C] | $ )
| ABC
(?: [^D] | $ )
)
|
(?: # Handle 'IJ`
I
(?: [^J] | $ )
)
)+
$