Couchbase xdcr regex - Как исключить ключи с помощью regex?

Я пытаюсь исключить передачу определенных документов в ES с использованием XDCR. У меня есть следующее регулярное выражение, которое фильтрует ABCD и IJ

https://regex101.com/r/gI6sN8/11

Теперь я хочу использовать это регулярное выражение в фильтрации XDCR

^ (?!.(ABCD | IJ)).$

Как исключить ключи с помощью регулярных выражений?

РЕДАКТИРОВАТЬ:
Что делать, если я хочу выбрать все, что не содержит ABCDE и ABCHIJ.
Я старался

https://regex101.com/r/zT7dI4/1

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] | $ )
      )
 )+
 $
Другие вопросы по тегам