Выражения

Синтаксис

В данной статье при описании выражений приняты следующие обозначения:

  • Элементы выражений разделены тильдой.

  • Круглые скобки служат для группировки элементов выражения.

  • Если в выражении используется литерал скобок или других символов, они заключаются в кавычки: "(". "NEWLINE" обозначает перевод строки.

  • Квантификаторы после элементов и групп обозначают количество повторений:

    • ? — элемент необязателен, может отсутствовать в выражении;

    • + — элемент обязателен и может повторяться в выражении несколько раз;

    • * — элемент может отсутствовать или повторяться несколько раз.

Комментарий

Комментарий используется для целей документирования программного кода и обозначается символом #. Каждая строка комментария должна начинаться с символа #. В настоящее время VRL не поддерживает многострочные комментарии.

Примеры

# комментарий
# комментарий
# из нескольких строк

Ключевые слова

Ключевые слова — это зарезервированные слова, используемые для базовых функций языка, таких как работа с условиями (if). Они не могут использоваться для наименования переменных или других пользовательских директив. Следующие слова зарезервированы:

  • abort

  • as

  • break

  • continue

  • else

  • false

  • for

  • if

  • impl

  • in

  • let

  • loop

  • null

  • return

  • self

  • std

  • then

  • this

  • true

  • type

  • until

  • use

  • while

Пробелы

Пробел — это любая непустая строка, определенная свойством Unicode White_Space.

VRL является языком свободной формы, что означает, что все пробелы и отступы используются только для разделения токенов в грамматике и не влияют на семантику программы.

Литералы

Пустое значение (Null)

Литерал пустого значения представляет отсутствие определенного значения.

Пример

null

Логическое значение (Boolean)

Литерал типа логическое выражение представляет собой двоичное значение, которое может быть только истинным (true) или ложным (false).

Примеры

true
false

Целое число (Integer)

Литерал типа целое число — это десятичное представление 64-битного целого числа со знаком.

Характеристики

Ограничения

Целые числа в VRL могут находиться в диапазоне от -263 + 1 до 263 - 1. Числа за пределами этого диапазона "оборачиваются", то есть переносятся на другой конец диапазона.

Подчеркивание

В целых числах может использоваться символ _ для улучшения читаемости, например, для разделения разрядов. Например, 1_000_000.

Примеры

1_000_000
1000000

Число с плавающей точкой (Float)

Литерал типа число с плавающей точкой представляет собой десятичное представление 64-битного числа с плавающей точкой (в частности, тип "binary64", определенный в IEEE 754-2008), включая знак.

Десятичный литерал с плавающей точкой состоит из целой части (десятичные цифры), десятичной точки и дробной части (десятичные цифры).

Характеристики

Ограничения

Числа с плавающей точкой в VRL могут находиться в диапазоне от -1.7976931348623157E+308f64 до 1.7976931348623157E+308f64. Числа за пределами этого диапазона "оборачиваются", то есть переносятся на другой конец диапазона.

Подчеркивания

В числах с плавающей точкой может использоваться символ _ для улучшения читаемости, например, для разделения разрядов. Например, 1_000_000.0.

Примеры

1_000_000.01
1000000.01
1.001

Метка времени (Timestamp)

Литерал метки времени — это нативная метка времени, выраженная в формате RFC 3339 с точностью до наносекунды.

Метки времени определяются с помощью символа t и заключаются в одинарные кавычки (t'2021-02-11T10:32:50.553955473Z').

Примеры

t'2021-02-11T10:32:50.553955473Z'
t'2021-02-11T10:32:50.553Z'
t'2021-02-11T10:32:50.553-04:00'

Характеристики

Часовые пояса

Как определено в формате RFC 3339, литералы меток времени поддерживают UTC и локальные смещения времени.

Строка (String)

Литерал строки представляет собой строку, закодированную в UTF-8. Строковые литералы могут быть сырыми или интерпретированными.

Сырые (raw) строковые литералы состоят из неинтерпретированных (неявно закодированных в UTF-8) символов между одинарными кавычками и обозначаются символом s (s'…​'). В частности, обратная косая черта не имеет особого значения, и строка может содержать символы новой строки.

Интерпретированные строковые литералы представляют собой последовательности символов между двойными кавычками ("…​"). Внутри кавычек может находиться любой символ, кроме неэкранированного символа новой строки и неэкранированной двойной кавычки. Текст между кавычками представляет собой результат литерала, с экранированными символами, интерпретируемыми как показано ниже. Строки можно шаблонизировать, заключив переменные в {{..}}. Значения переменных вставляются в строку на указанной позиции.

Примеры

"Hello, world! 🌎"
"Hello, world! \u1F30E"
"Hello, \
world!"
"Hello, {{ planet }}!"
s'Hello, world!'
s'{ "foo": "bar" }'

Характеристики

Экранирование

Специальные символы, такие как символы новой строки, могут быть выражены с помощью экранирования обратной косой чертой.

Представление Описание

\u{7FFF}

Символ Unicode из 24 бит (до 6 цифр)

\n

Перевод строки

\r

Возврат каретки

\t

Табуляция

\\

Обратная косая черта

\0

Пустой символ

\"

Двойные кавычки

\'

Одинарные кавычки

\{

Фигурная скобка

Шаблоны

Строку можно шаблонизировать, заключив имя переменной в {{..}}. Значение переменной вставляется в строку на этой позиции во время выполнения. Переменная должна быть строкой. Поддерживаются только переменные. Если вы хотите вставить путь из события, вы должны сначала присвоить его переменной. Чтобы вставить {{ в строку, его можно экранировать с помощью символа \: \{{..\}}.

Многострочные литералы

Длинные строки можно разбить на несколько строк, добавив обратную косую черту перед символом новой строки. Символ новой строки и любые пробелы в начале следующей строки не будут включены в строку.

Конкатенация

Строки можно объединять с помощью оператора +.

Недопустимые символы

Недопустимые последовательности UTF-8 заменяются символом .

Регулярное выражение (Regex)

Литерал регулярного выражения представляет собой регулярное выражение, используемое для сопоставления и разбора строк.

Регулярные выражения определяются с помощью символа r и заключаются в одинарные кавычки: r'…​'. Используется синтаксис регулярных выражений Rust.

Для изучения регулярных выражений в VRL рекомендуется использовать редактор и тестер выражений Rustexp.

Обычные и специальные символы

Представление Описание Эквиваленты

a

Большинство символов представляют сами себя.

\x61

\u0061

\U00000061

\\

Специальные символы [ ] \ / ^ $ . | ? * + ( ) { } для представления самих себя должны быть экранированы.

\x5C

\x61

Шестнадцатеричный код символа ASCII из двух цифр.

a

\u0062

Шестнадцатеричный код символа Unicode из четырех цифр.

b

\U00000062

Шестнадцатеричный код символа Unicode из восьми цифр.

c

\x{00003A9} \u{000003A9} \U{3A9}

Любой шестнадцатеричный код, которому соответствует символ Unicode.

Ω

\t

Символ горизонтальной табуляции.

\x09

\n

Символ перевода строки

\x0A

\r

Символ возврата каретки.

\x0D

\v

Символ вертикальной табуляции.

\x0B

\a

Символ звукового сигнала.

\x07

\f

Символ смены страницы.

\x0C

Метасимволы и специальные символьные классы

Представление Описание Эквиваленты

.

Метасимвол, обозначающий любой символ, кроме символа перевода строки \n.

\p{Property}

Любой символ со свойством Unicode, указанным в фигурных скобках.

Список поддерживаемых свойств описан в документе.

\P{Property}

Любой символ, не имеющий свойства Unicode, указанного в фигурных скобках.

\pX

Любой символ Unicode, относящийся к классу, обозначенному одной буквой:

  • L — "алфавитные" символы: буквы и идеограммы всех письменностей;

  • M — диакритические символы;

  • N — цифры;

  • P — знаки препинания;

  • S — знаки валют, математические и иные обозначения;

  • Z — пробельные символы, разделители строк и абзацев;

  • C — управляющие символы, символы из областей для частного использования и нераспределенных областей.

\p{Property}

\PX

Любой символ Unicode, не относящийся к классу, обозначенному одной буквой.

\P{Property}

[[:ascii:]]

Любой символ ASCII.

[\x00-\x7F]

[[:print:]]

Любой символ ASCII, доступный для печати: любой символ, кроме управляющих.

[ -~]

[[:graph:]]

Любой отображаемый символ ASCII: любой символ, кроме управляющих и пробельных.

[!-~]

\w

Любой символ Unicode, входящий в состав слов: буква или идеограмма любой письменности, диакритический символ, цифра, знак пунктуации, соединяющий слова (например, _), управляющий символ для лигатур.

[\p{Alphabetic}\p{M}\d\p{Pc}\p{Join_Control}]

\W

Любой символ Unicode, не входящий в состав слов.

[^\w]

[[:word:]]

Любая буква базового латинского алфавита, цифра ASCII или подчеркивание.

[0-9A-Za-z_]

(?-u:\w)

[\w&&\p{ascii}]

[[:alnum:]]

Любая буква базового латинского алфавита или цифра ASCII.

[0-9A-Za-z]

[[:alpha:]]

Любая буква базового латинского алфавита.

[A-Za-z]

[[:upper:]]

Любая прописная буква базового латинского алфавита.

[A-Z]

[[:lower:]]

Любая строчная буква базового латинского алфавита.

[a-z]

\d

Любая десятичная цифра Unicode.

\p{Nd}

\D

Любой символ, кроме десятичных цифр Unicode.

[^\d]

[[:digit:]]

Любая десятичная цифра ASCII.

[0-9]

[\d&&\p{ascii}]

(?-u:\d)

[[:xdigit:]]

Любая шестнадцатеричная цифра.

[0-9A-Fa-f]

[[:punct:]]

Любой знак препинания ASCII.

[!-/:@\\\[\]\{\}\(\)~`]

\s

Любой пробельный символ (символ со свойством Unicode Whitespace).

\p{White_Space}

\S

Любой символ, кроме пробельных.

\P{White_Space}

[[:space:]]

Любой пробельный символ ASCII.

[\t\n\v\f\r ]

[[:blank:]]

Пробел или горизонтальная табуляция.

[\t ]

[[:cntrl:]]

Любой управляющий символ ASCII.

[\x00-\x1F\x7F]

Символьные классы и перечисление

Представление Описание Найденные совпадения

xy

Последовательность x и y.

xy

x|y

Перечисление: одна из последовательностей x или y, причем предпочтение отдается x.

x

[xyz]

Объединение: символы из указанных в квадратных скобках.

x, y, z

[^xyz]

Отрицание: все символы, кроме указанных в квадратных скобках.

Все символы, кроме x, y и z.

[a-z]

Диапазон: все символы между указанными.

Символы от a до z включительно.

[x[^xyz]]

Вложенный класс: все символы, указанные хотя бы в одном из классов.

Все символы, кроме y и z.

[a-y&&xyz]

Пересечение: символы, которые входят в оба класса.

x, y

[0-9—​4]

Разность: символы первого класса, которые не входят во второй класс. (Эквивалентно записи [0-9&&[^4]]).

Все десятичные цифры ASCII, кроме 4.

[a-g~~b-h]

Симметрическая разность: символы, которые входят лишь в один класс из указанных.

a, h

Приоритет в перечислениях:

В перечислениях проверяется каждый указанный вариант слева направо, поиск прекращается при первом совпадении.

Пример

Пример 1. Исходный код
.res = parse_regex_all!("authentication", r'authentication|auth', numeric_groups: true)
Пример 2. Результат
[
  {
    "0": "authentication"
  }
]

Здесь функция с шаблоном r'authentication|auth' сначала пытается найти последовательность "authentication", и поскольку она полностью соответствует строке, именно это совпадение и будет возвращено. Однако, если изменить порядок вариантов, изменится и результат.

Пример 3. Исходный код
.res = parse_regex_all!("authentication", r'auth|authentication', numeric_groups: true)
Пример 4. Результат
[
  {
    "0": "auth"
  }
]

При таком порядке вариантов сначала будет найдено "auth". На этом поиск остановится и вернет "auth", несмотря на то, что более длинный вариант "authentication" также соответствует строке.

Порядок вычисления символьных классов:

  1. Диапазоны: выражение r'[а-яё]' равнозначно выражению r'[[а-я]ё]' и выбирает все строчные буквы русского алфавита.

  2. Объединение: выражение r'[ab&&bc]' равнозначно выражению r'[[ab]&&[bc]]' и выбирает символы, которые входят в оба класса.

  3. Пересечение, разность, симметрическая разность имеют одинаковый приоритет и вычисляются по порядку слева направо. Например, следующее выражение:

    r'[\pL--\p\{Greek}&&\p\{Uppercase}]'

    равнозначно такому выражению:

    r'[[\pL--\p\{Greek}]&&\p\{Uppercase}]'

    Эти выражения выбирают все "алфавитные" символы в верхнем регистре, кроме греческих.

  4. Отрицание: выражение r'[^a-z&&[:xdigit:]]' равнозначно выражению r'[^[a-z&&[:xdigit:]]]'.

    Эти выражения выбирают все символы, кроме тех, которые одновременно являются шестнадцатеричными цифрами и строчными латинскими буквами.

Группировка

Группы в круглых скобках определяют области действия флагов, квантификаторов, и перечислений.

Регулярные выражения поддерживают захват групп, что позволяет извлекать части шаблона как строки. Именованные группы захвата позволяют связать результаты извлечения с ключами.

Представление Описание

(exp)

Нумерованная группа захвата.

(?P<name>exp)

Именованная группа захвата. Возможно обращение как по номеру, так и по ключу, указанному в угловых скобках. (Эквивалентно записи (?<name>exp).)

Имя может включать "алфавитные" символы и цифры Unicode, а также символы .,_[] и начинаться с "алфавитного" символа либо подчеркивания.

(?:exp)

Незахватываемая группа.

(?x)

Установка флага x внутри текущей группы.

(?-x)

Выключение флага x внутри текущей группы.

(?x-y:exp)

Установка флага x и выключение флага y внутри незахватываемой группы.

Пример

Рассмотрим следующую функцию:

Пример 5. Исходный код
.res = parse_regex!("2012-12-12", r'(?P<y>\d{4})-(?P<m>\d{2})-(?P<d>\d{2})')
Пример 6. Результат
{
  "res": {
    "d": "12",
    "m": "12",
    "y": "2012"
  }
}

Данная функция извлекает из строки с датой вида YYYY-MM-DD группы, содержащие год, месяц и число с ключами y, m и d соответственно.

Квантификаторы

Квантификатор после символа, символьного класса или группы определяет, сколько раз может встречаться предшествующее выражение.

При жадной квантификации возвращается наиболее длинная строка из возможных соответствий, при ленивой — наиболее короткая.

Представление Описание Поведение

x?

Ноль или одно повторение x.

Жадная квантификация

x*

Ноль или больше повторений x.

Жадная квантификация

x+

Одно или больше повторений x.

Жадная квантификация

x??

Ноль или одно повторение x.

Ленивая квантификация

x*?

Ноль или больше повторений x.

Ленивая квантификация

x+?

Одно или больше повторений x.

Ленивая квантификация

x{n}

В точности n повторений x. Аналогично записи x{n}?.

x{n,}

Как минимум n повторений x.

Жадная квантификация

x{n,m}

Между n и m повторений x

Жадная квантификация

x{n,}?

Как минимум n повторений x.

Ленивая квантификация

x{n,m}?

Между n и m повторений x

Ленивая квантификация

Примеры

Следующая функция ищет последовательности символов, заключенные в квадратные скобки.

Пример 7. Исходный код
.res = parse_regex_all!("[ERROR] [2024-10-05 10:01:00] [code: 500]", r'\[.*\]', numeric_groups: true)
Пример 8. Результат
[
  {
    "0": "[ERROR] [2024-10-05 10:01:00] [code: 500]"
  }
]

Если заменить квантификатор на ленивый: r'\[.*?\]', функция вернет отдельные подстроки в квадратных скобках.

Пример 9. Исходный код
.res = parse_regex_all!("[ERROR] [2024-10-05 10:01:00] [code: 500]", r'\[.*?\]', numeric_groups: true)
Пример 10. Результат
[
  {
    "0": "[ERROR]"
  },
  {
    "0": "[2024-10-05 10:01:00]"
  },
  {
    "0": "[code: 500]"
  }
]

Позиция в тексте

Следующие символы позволяют указать положение шаблона относительно начала и конца строки, а также границ слов.

Представление Описание

^

Начало текста (в многострочном режиме — начало строки).

$

Конец текста (в многострочном режиме — конец строки).

\A

Только в начале текста, в т. ч. в многострочном режиме.

\z

Только в конце текста, в т. ч. в многострочном режиме.

\b

Граница слова Unicode: символ, соответствующий классу \w с одной стороны, и символ, соответствующий классу \W, либо граница текста, с другой стороны.

\B

Не на границе слова Unicode.

\b{start}, \<

Начало слова Unicode: символ класса \W или начало текста слева, символ класса \w справа.

\b{end}, \>

Конец слова Unicode: символ класса \w слева, символ класса \w или конец текста справа.

\b{start-half}

Проверка начала слова Unicode только слева: символ класса \W или начало текста.

\b{end-half}

Проверка конца слова Unicode только справа: символ класса \W или конец текста.

Примеры

Следующая функция возвращает последовательности алфавитно-цифровых и соединительных символов на границе слова.

Пример 11. Исходный код
.res = parse_regex_all!("@guest, @superuser, @root", r'(?P<user>\b\w+)')
Пример 12. Результат
[
  {
    "user": "guest"
  },
  {
    "user": "superuser"
  },
  {
    "user": "root"
  }
]

Чтобы получить последовательности с символом @, изменим проверку начала слова.

Пример 13. Исходный код
.res = parse_regex_all!("@guest, @superuser, @root", r'(?P<user>\b{start-half}@\w+)')
Пример 14. Код
[
  {
    "user": "@guest"
  },
  {
    "user": "@superuser"
  },
  {
    "user": "@root"
  }
]

Флаги

Регулярные выражения позволяют использовать флаги — модификаторы, которые изменяют поведение поиска для всего выражения или группы. Флаги могут быть объединены: r'(?ixm)pattern', r'(?im)pattern'. Флаги можно включать и выключать внутри выражения.

Опция Описание Состояние по умолчанию

i

Режим без учета регистра: буквы в выражении соответствуют и прописным, и строчным буквам в строке.

Выключен

m

Многострочный режим:

  • ^ соответствует началу новой строки.

  • $ соответствует концу строки.

Выключен

x

Режим с поддержкой комментариев. Строчные комментарии должны начинаться с символа #.

Пробелы при включенном режиме игнорируются. Чтобы добавить в шаблон пробел, можно использовать экранирование: \ ` или шестнадцатеричный код: \x20.

Выключен

s

Разрешает метасимволу точки . соответствовать символу новой строки \n.

Выключен

U

Меняет местами значение квантификаторов x* и x*? (ленивый режим).

Выключен

u

Поддержка Unicode.

Включен

Примеры

Рассмотрим следующую функцию:

Пример 15. Исходный код
.res = parse_regex!("AaAaAbbBBBb", r'(?i)a+(?-i)b+', numeric_groups: true)
Пример 16. Результат
{
  "0": "AaAaAbb"
}

В начале регулярного выражения включается регистронезависимый режим, поэтому a+ соответствует буквам a и A. Однако b+, после выключения регистронезависимого режима, соответствует только строчной b.

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

Пример 17. Исходный код
replace_with("2022-01-05, 2023-08-25 и 2024-10-18", r'(?x)
  (?P<y>\d{4}) # год из 4 цифр Unicode
  -
  (?P<m>\d{2}) # месяц из 2 цифр Unicode
  -
  (?P<d>\d{2}) # день из 2 цифр Unicode
') -> |match| {
    to_string(match.d) + "/" + to_string(match.m) + "/" + to_string(match.y)
}
Пример 18. Результат
"05/01/2022, 25/08/2023 и 18/10/2024"

Массив

Литерал массива представляет собой набор выражений, разделенных запятыми, который создает непрерывный массив. Массив может быть динамически расширен.

Примеры

Пример 19. Пустой массив
[]
Пример 20. Массив из строк
["первый", "второй", "третий"]
Пример 21. Массив из литералов разного типа, включая объект
["смешанный", 1, 1.0, true, false, {"foo": "bar"}]
Пример 22. Вложенные массивы
[
  "первый-уровень",
  [
    "второй-уровень",
    [
      "третий-уровень"
    ]
  ]
]
Пример 23. Массив из динамических выражений
[.поле1, .поле2, to_int!("2"), variable_1]
Пример 24. Массив из динамических выражений
[
  "выражения",
  1 + 2,
  2 == 5,
  true || false
]

Объект

Литерал объекта представляет собой расширяемую структуру ключ/значение, которая синтаксически эквивалентна JSON-объекту.

Верно сформированный JSON-документ является допустимым объектом VRL.

Характеристики

Упорядочивание

Поля объекта упорядочены по ключу в алфавитном порядке по возрастанию. Таким образом, операции, такие как кодирование в JSON, производят строку с ключами, упорядоченными в алфавитном порядке.

Примеры

Пример 25. Объект с вложенными массивом и объектом
{
  "поле1": "значение1",
  "поле2": [
      "значение2",
      "значение3",
      "значение4"
   ],
  "поле3": {
    "поле4": "значение5"
  }
}
Пример 26. Массив со значениями, представленными путями и переменными
{
  "поле1": ."некий_путь",
  "поле2": some_variable,
  "поле3": {
    "вложенное_поле": "некое значение"
  }
}

Динамические выражения

Переменная

Выражение переменной именует переменные. Переменная представляет собой последовательность из одной или нескольких букв, цифр и подчеркиваний. Первый символ в переменной должен быть буквой или цифрой.

Синтаксис

first ~ (trailing)*
Элемент О писание

first

Первый символ может быть только буквенно-цифровым символом (a-zA-Z0-9).

trailing

Последующие символы должны содержать только ASCII буквенно-цифровые символы и подчеркивания (a-zA-Z0-9_).

Примеры

Простая переменная

Пример 27. Программа VRL
my_variable = 1
Пример 28. Результат
1

Переменная с путем

Пример 29. Программа VRL
my_object = { "one": 1 }
my_object.one
Пример 30. Результат
1
Элемент Описание

target

Цель должна быть путем с возможной второй переменной для обработки ошибок, если правая часть может возвращать ошибки.

error

Позволяет необязательное присваивание ошибок, когда выражение справа может возвращать ошибки. Это обычно используется при вызове функций, которые могут возвращать ошибки.

operator

Оператор разделяет target и expression и определяет условия присваивания.

expression

Если target — это переменная, expression может быть любым выражением.

Если target — это путь, expression может быть любым выражением, которое возвращает поддерживаемый тип значения объекта (то есть выражение, не являющееся регулярным).

Примеры

Присваивание пути

Пример 31. Программа VRL
.message = "Hello, World!"

Присваивание по вложенному пути

Пример 32. Программа VRL
.parent.child = "Hello, World!"

Двойное присваивание

Пример 33. Программа VRL
.first = .second = "Hello, World!"

Присваивание элемента массива

Пример 34. Программа VRL
.array[1] = "Hello, World!"

Присваивание переменной

Пример 35. Программа VRL
my_variable = "Hello, World!"
Пример 36. Результат
Hello, World!

Присваивание со слиянием объектов

Пример 37. Программа VRL
my_variable = {"message": "Hello, World!"}
my_variable |= {"level": "info"}
Пример 38. Результат
{
  "level": "info",
  "message": "Hello, World!"
}

Присваивание с возможностью ошибки (успех)

Пример 39. Программа VRL
.parsed, .err = parse_json("{\"Hello\": \"World!\"}")

Присваивание с возможностью ошибки (ошибка)

Пример 40. Программа VRL
.parsed, .err = parse_json("malformed")

Путь

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

Синтаксис

root_path ~ path_segments
Элемент Описание

root_path

Все пути должны начинаться с . или %:

  • Символ . представляет корень события.

  • Символ % представляет корень метаданных события.

path_segments

Сегменты пути обозначают сегмент вложенного пути. Каждый сегмент должен быть отделен точкой в начале и может содержать только буквенно-цифровые символы и подчеркивание (a-zA-Z0-9_). Сегменты, содержащие символы вне этого диапазона, должны быть заключены в кавычки.

Примеры

Корневой путь события

Пример 41. Событие Vector
{
  "message": "Hello, World!"
}
Пример 42. Программа VRL
.
Пример 43. Результат
{
  "message": "Hello, World!"
}

Корневой путь метаданных

Пример 44. Событие Vector
{
  "message": "Hello, World!"
}
Пример 45. Программа VRL
%
Пример 46. Результат
{}

Путь верхнего уровня

Пример 47. Событие Vector
{
  "message": "Hello, World!"
}
Пример 48. Программа VRL
.message
Пример 49. Результат
Hello, World!

Вложенный путь

Пример 50. Событие Vector
{
  "parent": {
    "child": "Hello, World!"
  }
}
Пример 51. Программа VRL
.parent.child
Пример 52. Результат
Hello, World!

Объединение вложенных путей

Пример 53. Событие Vector
{
  "grand_parent": {
    "parent2": {
      "child": "Hello, World!"
    }
  }
}
Пример 54. Программа VRL
.grand_parent.parent1.child || .grand_parent.parent2.child
Пример 55. Результат
Hello, World!

Путь в кавычках

Пример 56. Событие Vector
{
  "parent.key.with.special characters": {
    "child": "Hello, World!"
  }
}
Пример 57. Программа VRL
."parent.key.with.special characters".child
Пример 58. Результат
Hello, World!

Путь к первому элементу массива

Пример 59. Событие Vector
{
"массив": [
  "первый",
  "второй"
]
}
Пример 60. Программа VRL
."массив"[0]
Пример 61. Результат
"первый"

Путь ко второму элементу массива

Пример 62. Событие Vector
{
  "массив": [
    "первый",
    "второй"
  ]
}
Пример 63. Программа VRL
."массив"[1]
Пример 64. Результат
"второй"

Индекс

Выражение индекса обозначает элемент массива. Индексы массивов в VRL начинаются с нуля.

Синтаксис

"[" ~ index ~ "]"
Элемент Описание

index

Индекс представляет собой нулевую позицию элемента.

Примеры

Выражение индекса массива

Пример 65. Событие Vector
{
  "массив": [
    "первый",
    "второй"
  ]
}
Пример 66. Программа VRL
."массив"[0]
Пример 67. Результат
"первый"

Присваивание

Выражение присваивания присваивает результат выражения справа от знака равенства цели слева (пути или переменной).

Синтаксис

target ~ ("," ~ error)? ~ operator ~ expression
Аргумент Значение

target

Цель должна быть переменной, индексом или путем. Возможно присваивание сразу нескольким целям, разделенным оператором =.

error

Позволяет необязательное присваивание ошибок, когда выражение справа может возвращать ошибки. Это обычно используется при вызове функций, которые могут возвращать ошибки.

operator

Оператор разделяет target и expression и определяет условия присваивания:

  • = — обычное присваивание;

  • |= — присваивание со слиянием объектов.

expression

Если target — это переменная, expression может быть любым выражением.

Если target — это путь, expression может быть любым выражением, которое возвращает поддерживаемый тип значения объекта (то есть, выражение, не являющееся регулярным).

Характеристики

Двойное присваивание

Оператор = может использоваться для присваивания нескольким целям сразу. Двойное присваивание неприменимо, если используется присваивание ошибок.

Присваивание со слиянием

Оператор |= обновляет поля в целевом объекте на основе содержимого объекта из expression. При этом:

  • Поля, которые есть только в целевом объекте, остаются неизменными.

  • Поля, которые есть только во втором объекте, добавляются в целевой.

  • Если поле существует в обоих объектах, значение поля из expression заменяет значение из целевого объекта, вложенные структуры при этом не учитываются. Чтобы объединить при слиянии вложенные поля, используйте функцию merge с параметром deep=true.

Примеры

Присваивание пути

Пример 68. Программа VRL
.message = "Hello, World!"
Пример 69. Результат
{
  "message": "Hello, World!",
}

Присваивание по вложенному пути

Пример 70. Программа VRL
.parent.child = "Hello, World!"

Двойное присваивание

Пример 71. Программа VRL
.first = .second = "Hello, World!"
Пример 72. Результат
{
  "first": "Hello, World!",
  "second": "Hello, World!"
}

Присваивание элементу массива

Пример 73. Программа VRL
.array[1] = "Hello, World!"

Присваивание переменной

Пример 74. Программа VRL
my_variable = "Hello, World!"
Пример 75. Результат
Hello, World!

Присваивание со слиянием объектов

Пример 76. Программа VRL
my_variable = {
  "parent1": {
    "child1": 1,
    "child2": 2
  },
  "parent2": {
    "child3": 3
  }
}
my_variable |= {
  "parent1": {
    "child2": 4,
    "child5": 5
  }
}
Пример 77. Результат
{
  "parent1": {
    "child2": 4,
    "child5": 5
  },
  "parent2": {
    "child3": 3
  }
}

Присваивание с возможностью ошибки (успех)

Пример 78. Программа VRL
.parsed, .err = parse_json("{\"Hello\": \"World!\"}")
Пример 79. Результат
{
  "parsed": {
    "Hello": "World!"
  }
}

Присваивание с возможностью ошибки (ошибка)

Пример 80. Программа VRL
.parsed, .err = parse_json("malformed")
Пример 81. Результат
{
  "err": "malformed"
}

Арифметическое выражение

Арифметическое выражение выполняет операцию над двумя выражениями (операндами) согласно оператору.

Хотя арифметическое выражение обычно применяется к числам, его можно и с другими типами, такими как строки.

Синтаксис

expression ~ (operator ~ expression)+
Элемент Описание

expression

Выражение может быть любым выражением, которое возвращает тип, допустимый для оператора.

operator

Оператор определяет операцию, выполняемую над операндами слева и справа. Существующие операторы:

  • + — сложение чисел или конкатенация строк;

  • - — вычитание чисел;

  • * — перемножение чисел или повторение строки указанное число раз;

  • / — деление чисел (не целочисленное).

Характеристики

Арифметические операции над числами разных типов возвращают числа с плавающей точкой.

Действует стандартный приоритет операций: умножение и деление выполняются до сложения и вычитания. Для изменения приоритета используются скобки.

Примеры

Сложение целых чисел

Пример 82. Программа VRL
1 + 1
Пример 83. Результат
2

Сложение чисел с плавающей точкой

Пример 84. Программа VRL
0.1 + 0.2
Пример 85. Результат
0.30000000000000004
Некоторые десятичные дроби не могут быть точно представлены в двоичном виде, что приводит к небольшим неточностям в вычислениях (например, 0.1 + 0.2 != 0.3).

Сложение чисел разных типов

Пример 86. Программа VRL
1 + 1.0
Пример 87. Результат
2

Сложение строк

Пример 88. Программа VRL
"Hello" + ", " + "World!"
Пример 89. Результат
Hello, World!

Вычитание целых чисел

Пример 90. Программа VRL
2 - 1
Пример 91. Результат
1

Вычитание чисел с плавающей точкой

Пример 92. Программа VRL
2.0 - 1.0
Пример 93. Результат
1

Вычитание чисел разного типа

Пример 94. Программа VRL
2.0 - 1
Пример 95. Результат
1

Перемножение целых чисел

Пример 96. Программа VRL
2 * 1
Пример 97. Результат
2

Перемножение чисел с плавающей точкой

Пример 98. Программа VRL
2.0 * 1.0
Пример 99. Результат
2

Перемножение чисел разного типа

Пример 100. Программа VRL
2.0 * 1
Пример 101. Результат
2

Умножение строки на число

Пример 102. Программа VRL
"строка" * 2
Пример 103. Результат
"строкастрока"

Деление целых чисел

Пример 104. Программа VRL
2 / 1
Пример 105. Результат
2

Деление чисел с плавающей точкой

Пример 106. Программа VRL
2.0 / 1.0
Пример 107. Результат
2

Деление чисел разных типов

Пример 108. Программа VRL
2.0 / 1
Пример 109. Результат
2

Стандартный приоритет операций

Пример 110. Программа VRL
5 + 6 × 9 - 7
Пример 111. Результат
52

Задание приоритета с помощью скобок

Пример 112. Программа VRL
(5 + 6) × (9 - 7)
Пример 113. Результат
22

Для нахождения остатка используйте функцию mod.

Пример 114. Программа VRL
mod(3, 2)
Пример 115. Результат
1

Сравнение

Выражение сравнения сравнивает два выражения (операнда) и возвращает логическое значение в соответствии с оператором.

Синтаксис

expression ~ operator ~ expression
Элемент Описание

expression

Операнд может быть любым выражением, которое возвращает тип, допустимый для оператора.

operator

Оператор определяет операцию, выполняемую над операндами слева и справа:

  • == — равно;

  • != — неравно;

  • > — больше;

  • >= — больше или равно;

  • < — меньше;

  • <= — меньше или равно.

Характеристики

Равенство и неравенство Операторы == и != предназначены для сравнения между собой любых значений. Числовые значения разных типов могут быть равными, другие значения считаются равными, только если относятся к одному типу.

Сравнение порядка Операторы сравнения >, <, >= и <= применимы только к числам, строкам и меткам времени.

При сравнении строк используется лексикографический порядок, где символы сравниваются последовательно, на основе их номеров в таблице Unicode.

При сравнении меток времени большими считаются метки более поздней даты.

Примеры

Равенство чисел

Пример 116. Программа VRL
1 == 1.0
Пример 117. Результат
true

Неравенство чисел

Пример 118. Программа VRL
2 * 2 != 5
Пример 119. Результат
true

Больше или равно

Пример 120. Программа VRL
2 >= 2.0
Пример 121. Результат
true

Больше

Пример 122. Программа VRL
2 > 1
Пример 123. Результат
true

Меньше или равно

Пример 124. Программа VRL
2.0 <= 2
Пример 125. Результат
true

Меньше

Пример 126. Программа VRL
1 < 2
Пример 127. Результат
true

Сравнение временных меток

Пример 128. Программа VRL
t'2024-04-04T22:22:22.234142+01:00' > t'2024-04-04T22:22:22.234142+04:00'
Пример 129. Результат
true

Сравнение строк

Пример 130. Программа VRL
"ё" > "я"
Пример 131. Результат
true

Сравнение объектов

Пример 132. Программа VRL
{"key1": "value1", "key2": "value2"} == {"key2": "value2", "key1": "value1"}
Пример 133. Результат
true

Сравнение пустых значений

Пример 134. Программа VRL
null == null
Пример 135. Результат
true

Сравнение значений разных типов

Пример 136. Программа VRL
2 == "2"
Пример 137. Результат
false

Логическое выражение

Выражение логического типа сравнивает два выражения (операнды), прекращая вычисление на последнем выражении, вычисленном в соответствии с оператором.

Синтаксис

Пример 138. Унарные операции
operator ~ expression
Пример 139. Бинарные операции
expression ~ operator ~ expression
Элемент Описание

expression

Операнд может быть любым выражением, которое возвращает допустимый тип, определенный оператором.

operator

Оператор определяет операцию, выполняемую над операндами:

  • && — конъюнкция (AND);

  • || — дизъюнкция (OR);

  • ! — отрицание (NOT).

Примеры

AND

Пример 140. Программа VRL
true && true
Пример 141. Результат
true

OR с логическим значением

Пример 142. Программа VRL
false || "foo"
Пример 143. Результат
foo

OR с пустым значением

Пример 144. Программа VRL
null || "foo"
Пример 145. Результат
foo

NOT

Пример 146. Программа VRL
!false
Пример 147. Результат
true

Вызов функции

Выражение вызова функции вызывает встроенные функции VRL.

Синтаксис

function ~ abort? ~ "(" ~ arguments? ~ ")" ~ closure?
Элемент синтаксиса Значение

function

Имя встроенной функции.

abort

Прерывание — литерал !, который можно использовать с функциями, возвращающими ошибки, для прерывания программы, если функция возвращает ошибку:

result = f!()

В противном случае ошибки должны обрабатываться:

result, err = f()

Отсутствие обработки ошибок от функций, которые могут возвращать ошибку, приводит к ошибкам на этапе компиляции. Смотрите Справочник ошибок VRL для дополнительной информации.

arguments

Выражения, разделенные запятыми, которые могут дополнительно предваряться документированным именем.

closure

Замыкание — необязательный фрагмент кода, разрешенный вызовом функции. Замыкание применяется преимущественно в функциях, выполняющих итерации по коллекциям. Пример синтаксиса:

for_each([]) -> |index, value| {
...
}

Примеры

Позиционный вызов функции

Пример 148. Программа VRL
split("hello, world!", ", ")
Пример 149. Результат
[
"hello",
"world!"
]

Вызов функции с именованными аргументами (упорядоченными)

Пример 150. Программа VRL
split("hello, world!", pattern: ", ")
Пример 151. Результат
[
  "hello",
  "world!"
]

Вызов функции с именованными аргументами (неупорядоченными)

Пример 152. Программа VRL
split(pattern: ", ", value: "hello, world!")
Пример 153. Результат
[
  "hello",
  "world!"
]

Объединение

Выражение объединения состоит из нескольких выражений (операндов), разделенных оператором объединения ??. Логика объединения позволяет выбирать из списка выражений первое значение, которое соответствует заданному условию.

Оператор ?? полезен при обработке ошибок, так как позволяет задавать альтернативные способы обработки данных.

Синтаксис

expression ~ (operator ~ expression)+
Элемент Описание

expression

Операнд может быть любым выражением.

operator

Оператор разделяет два или более выражения.

Примеры

Объединение при ошибках

Пример 154. Программа VRL
parse_syslog("не Syslog") ?? parse_common_log("не Common Log Format") ?? "malformed"
Пример 155. Результат
malformed

Условие

Выражение условия (if) определяет условное выполнение двух ветвей в зависимости от значения логического выражения. Если логическое выражение оценивается как истинное (true), выполняется ветвь "if". В противном случае выполняется ветвь "else", если она присутствует.

Синтаксис

"if" ~ predicate ~ block ~ ("else if" ~ predicate ~ block)* ~ ("else" ~ block)?
Элемент Описание

predicate

Предикат должен быть выражением, которое приводится к значению логического типа. Если логическое значение не возвращается, возникает ошибка на этапе компиляции. Предикат может содержать несколько выражений. Несколько предикатов выражений должны быть заключены в скобки. Выражения должны быть разделены точкой с запятой (;) или новой строкой.

Примеры

Условие if true

Пример 156. Программа VRL
if true {
  "Hello, World!"
}
Пример 157. Результат
Hello, World!

Условие if false

Пример 158. Программа VRL
if false {
# not evaluated
  null
}
Пример 159. Результат
null

Условие if/else

Пример 160. Программа VRL
if false {
# not evaluated
  null
} else {
  "Hello, World!"
}
Пример 161. Результат
Hello, World!

Условие if … else if … else

Пример 162. Программа VRL
if false {
# not evaluated
  null
} else if false {
# not evaluated
  null
} else {
  "Hello, World!"
}
Пример 163. Результат
Hello, World!

Многострочное выражение

Пример 164. Программа VRL
x = 3
if (x = x + 1; x == 5) {
# not evaluated
  null
} else if (
  x = x + 1
  x == 5
) {
  "Hello, World!"
}
Пример 165. Результат
Hello, World!

Блок

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

Блоки не могут быть пустыми. Сочетание фигурных скобок без содержимого ({}) рассматривается как пустой объект.

Синтаксис

"{" ~ "NEWLINE"* ~ expressions ~ "NEWLINE"* ~ "}"
Элемент Описание

function

Имя встроенной функции.

expressions

Одно или несколько выражений.

Примеры

Простой блок

Пример 166. Программа VRL
{
  message = "{\"Hello\": \"World!\"}"
  parse_json!(message)
}
Пример 167. Результат
{
  "Hello": "World!"
}

Присваивание в блоке

Пример 168. Программа VRL
.structured = {
  message = "{\"Hello\": \"World!\"}"
  parse_json!(message)
}

Прерывание

Выражение abort приводит к завершению программы VRL, прерывая любые изменения, вносимые в событие.

Синтаксис

abort ~ message?
Элемент Описание

message

Необязательное отладочное сообщение, которое может быть использовано в диагностических целях и включается в метаданные события, отброшенного при преобразовании remap.

Примеры

Игнорирование недопустимых событий

Пример 169. Событие Vector
{
  "message": "hello world"
}
Пример 170. Программа VRL
if contains(string!(.message), "hello") {
  abort
}
.message = "not hello world"
Пример 171. Результат
{
  message": "hello world"
}