Синтаксис регулярных выражений

Регулярное выражение (regex) — это способ определения шаблонов поиска с использованием специальных символов и операторов.

Регулярное выражение (regex) — это способ определения шаблонов поиска с использованием специальных символов и операторов. Эти шаблоны позволяют вам сопоставлять последовательности символов в строках.

В OpenSearch вы можете использовать регулярные выражения в следующих типах запросов:

  • regexp
  • query_string

OpenSearch использует движок регулярных выражений Apache Lucene, который имеет свой собственный синтаксис и ограничения. Он не использует регулярные выражения, совместимые с Perl (PCRE), поэтому некоторые знакомые функции регулярных выражений могут вести себя иначе или не поддерживаться.

Выбор между запросами regexp и query_string

Оба запроса regexp и query_string поддерживают регулярные выражения, но они ведут себя по-разному и служат для разных случаев использования.

Особенность Запрос regexp Запрос query_string
Сопоставление шаблонов Шаблон regex должен соответствовать всему значению поля Шаблон regex может соответствовать любой части поля
Поддержка флагов Флаги включают необязательные операторы regex Флаги не поддерживаются
Тип запроса Запрос на уровне термина (не оценивается) Полнотекстовый запрос (оценивается и разбирается)
Лучший случай использования Строгое сопоставление шаблонов для полей типа keyword или exact Поиск в анализируемых полях с использованием гибкой строки запроса, поддерживающей шаблоны regex
Сложная композиция запросов Ограничена шаблонами regex Поддерживает AND, OR, подстановочные знаки, поля, увеличение и другие функции. См. Запрос query_string.

Зарезервированные символы

Движок регулярных выражений Lucene поддерживает все символы Unicode. Однако следующие символы рассматриваются как специальные операторы:

. ? + * | { } [ ] ( ) " \

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

@ & ~ < >

Чтобы сопоставить эти символы буквально, либо экранируйте их с помощью обратной косой черты (), либо оберните всю строку в двойные кавычки:

  • \&: Сопоставляет литерал &
  • \\: Сопоставляет литерал обратной косой черты ()
  • "hello@world": Сопоставляет полную строку hello@world

Стандартные операторы регулярных выражений

Lucene поддерживает основной набор операторов регулярных выражений:

  • . – Сопоставляет любой одиночный символ. Пример: f.n соответствует f, за которым следует любой символ, а затем n (например, fan или fin).

  • ? – Сопоставляет ноль или один из предыдущих символов. Пример: colou?r соответствует color и colour.

  • + – Сопоставляет один или более из предыдущих символов. Пример: go+ соответствует g, за которым следует один или более o (go, goo, gooo и так далее).

  • * – Сопоставляет ноль или более из предыдущих символов. Пример: lo*se соответствует l, за которым следует ноль или более o, а затем se (lse, lose, loose, loooose и так далее).

  • {min,max} – Сопоставляет конкретный диапазон повторений. Если max опущен, нет верхнего предела на количество сопоставляемых символов. Пример: x{3} соответствует ровно 3 x (xxx); x{2,4} соответствует от 2 до 4 x (xx, xxx или xxxx); x{3,} соответствует 3 или более x (xxx, xxxx, xxxxx и так далее).

  • | – Действует как логическое ИЛИ. Пример: apple|orange соответствует apple или orange.

  • ( ) – Группирует символы в подпаттерн. Пример: ab(cd)? соответствует ab и abcd.

  • [ ] – Сопоставляет один символ из набора или диапазона. Пример: [aeiou] соответствует любой гласной.

  • - – Когда предоставляется внутри скобок, указывает диапазон, если не экранирован или является первым символом внутри скобок. Пример: [a-z] соответствует любой строчной букве; [-az] соответствует -, a или z; [a\\-z] соответствует a, -, или z.

  • ^ – Когда предоставляется внутри скобок, действует как логическое НЕ, отрицая диапазон символов или любой символ в наборе. Пример: [^az] соответствует любому символу, кроме a или z; [^a-z] соответствует любому символу, кроме строчных букв; [^-az] соответствует любому символу, кроме -, a и z; [^a\\-z] соответствует любому символу, кроме a, -, и z.

Необязательные операторы

Вы можете включить дополнительные операторы регулярных выражений, используя параметр flags. Разделяйте несколько флагов с помощью |.

Следующие флаги доступны:

  • ALL (по умолчанию) – Включает все необязательные операторы.

  • COMPLEMENT – Включает ~, который отрицает следующее выражение. Пример: d~ef соответствует dgf, dxf, но не def.

  • INTERSECTION – Включает & как логический оператор И. Пример: ab.+&.+cd соответствует строкам, содержащим ab в начале и cd в конце.

  • INTERVAL – Включает синтаксис <min-max> для сопоставления числовых диапазонов. Пример: id<10-12> соответствует id10, id11 и id12.

  • ANYSTRING – Включает @ для сопоставления любой строки. Вы можете комбинировать это с ~ и & для исключений. Пример: @&.*error.*&.*[0-9]{3}.* соответствует строкам, содержащим как слово “error”, так и последовательность из трех цифр.

Неподдерживаемые функции

Движок Lucene не поддерживает следующие часто используемые якоря регулярных выражений:

  • ^ – Начало строки
  • $ – Конец строки

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

Пример использования регулярных выражений

Чтобы попробовать регулярные выражения, индексируйте следующие документы в индекс logs:

PUT /logs/_doc/1
{
  "message": "error404"
}
PUT /logs/_doc/2
{
  "message": "error500"
}
PUT /logs/_doc/3
{
  "message": "error1a"
}

Пример: Базовый запрос с использованием регулярных выражений

Следующий запрос regexp возвращает документы, в которых полное значение поля message соответствует шаблону “error”, за которым следует одна или более цифр. Значение не соответствует, если оно содержит шаблон только как подстроку:

GET /logs/_search
{
  "query": {
    "regexp": {
      "message": {
        "value": "error[0-9]+"
      }
    }
  }
}

Этот запрос соответствует error404 и error500:

{
  "took": 28,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "logs",
        "_id": "1",
        "_score": 1,
        "_source": {
          "message": "error404"
        }
      },
      {
        "_index": "logs",
        "_id": "2",
        "_score": 1,
        "_source": {
          "message": "error500"
        }
      }
    ]
  }
}

Пример: Использование необязательных операторов

Следующий запрос соответствует документам, в которых поле message точно соответствует строке, начинающейся с “error”, за которой следует число от 400 до 500, включительно. Флаг INTERVAL позволяет использовать синтаксис <min-max> для числовых диапазонов:

GET /logs/_search
{
  "query": {
    "regexp": {
      "message": {
        "value": "error<400-500>",
        "flags": "INTERVAL"
      }
    }
  }
}

Этот запрос также соответствует error404 и error500:

{
  "took": 22,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "logs",
        "_id": "1",
        "_score": 1,
        "_source": {
          "message": "error404"
        }
      },
      {
        "_index": "logs",
        "_id": "2",
        "_score": 1,
        "_source": {
          "message": "error500"
        }
      }
    ]
  }
}

Пример: Использование ANYSTRING

Когда флаг ANYSTRING включен, оператор @ соответствует всей строке. Это полезно в сочетании с пересечением (&), поскольку позволяет вам строить запросы, которые соответствуют полным строкам при определенных условиях.

Следующий запрос соответствует сообщениям, которые содержат как слово “error”, так и последовательность из трех цифр. Используйте ANYSTRING, чтобы утверждать, что все поле должно соответствовать пересечению обоих шаблонов:

GET /logs/_search
{
  "query": {
    "regexp": {
      "message.keyword": {
        "value": "@&.*error.*&.*[0-9]{3}.*",
        "flags": "ANYSTRING|INTERSECTION"
      }
    }
  }
}

Этот запрос соответствует error404 и error500:

{
  "took": 20,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "logs",
        "_id": "1",
        "_score": 1,
        "_source": {
          "message": "error404"
        }
      },
      {
        "_index": "logs",
        "_id": "2",
        "_score": 1,
        "_source": {
          "message": "error500"
        }
      }
    ]
  }
}

Обратите внимание, что этот запрос также будет соответствовать xerror500, error500x и errorxx500.