Spec-Zone.ru › Nim

std/nre

ИсточникРедактировать

Что такое NRE?

Библиотека регулярных выражений для Nim, использующая PCRE для сложной работы.

Для документации по написанию шаблонов существует официальная документация PCRE по шаблонам. Вы также можете найти множество сторонних документаций и инструментов в интернете.

Предупреждение: Если вы любите sequtils.toSeq, у нас плохие новости для вас. Эта библиотека не работает с ним из-за документированных ограничений компилятора. В качестве обходного решения используйте это:

Пример:

import std/nre
# either `import std/nre except toSeq` or fully qualify `sequtils.toSeq`:
import std/sequtils
iterator iota(n: int): int =
  for i in 0..<n: yield i
assert sequtils.toSeq(iota(3)) == @[0, 1, 2]
Примечание: Также существуют альтернативные пакеты Nim, такие как tinyre и regex.

Лицензирование

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

Пример:

import std/nre
import std/sugar
let vowels = re"[aeoui]"
let bounds = collect:
  for match in "moiga".findIter(vowels): match.matchBounds
assert bounds == @[1 .. 1, 2 .. 2, 4 .. 4]
from std/sequtils import toSeq
let s = sequtils.toSeq("moiga".findIter(vowels))
  # fully qualified to avoid confusion with nre.toSeq
assert s.len == 3

let firstVowel = "foo".find(vowels)
let hasVowel = firstVowel.isSome()
assert hasVowel
let matchBounds = firstVowel.get().captureBounds[-1]
assert matchBounds.a == 1

# as with module `re`, unless specified otherwise, `start` parameter in each
# proc indicates where the scan starts, but outputs are relative to the start
# of the input string, not to `start`:
assert find("uxabc", re"(?<=x|y)ab", start = 1).get.captures[-1] == "ab"
assert find("uxabc", re"ab", start = 3).isNone

Импорты

pcre, util, таблицы, strutils, options, unicode

Типы

CaptureBounds = distinct RegexMatch
Источник Редактировать
Captures = distinct RegexMatch
Источник Редактировать
InvalidUnicodeError = ref object of RegexError
  pos*: int                  ## the location of the invalid unicode in bytes
Выбрасывается при неудачном сопоставлении из-за некорректного Unicode в строках Источник Редактировать
Regex = ref object
  pattern*: string
  ## not nil
  ## nil
Представляет шаблон, к которому применяются сопоставления, созданный с помощью re(string). Примеры: re"foo", re(r"(*ANYCRLF)(?x)foo # comment"..
pattern: string
строка, используемая для создания шаблона. Подробности о том, как написать шаблон, см. в официальной документации PCRE по шаблонам.
captureCount: int
количество захватов, содержащихся в шаблоне.
captureNameId: Table[string, int]
таблица, сопоставляющая имена захватов с их числовыми идентификаторами.

Параметры

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

  • (?i) - регистронезависимый
  • (?m) - многострочный: ^ и $ соответствуют началу и концу строк, а не всей строки-предмета
  • (?s) - . также соответствует переводу строки (dotall)
  • (?U) - выражения по умолчанию не жадные. ? можно добавить к квалификатору, чтобы сделать его жадным
  • (?x) - пробелы и комментарии (#) игнорируются (extended)
  • (?X) - символьные экранирования без специального значения (\w против \a) считаются ошибками (extra)

Один или несколько из этих параметров могут появиться только в начале шаблона:

  • (*UTF8) - обрабатывать и шаблон, и строку-предмет как UTF-8
  • (*UCP) - свойства Unicode-символов; \w соответствует я
  • (*U) - комбинация двух вышеперечисленных параметров
  • (*FIRSTLINE*) - завершается неудачей, если нет совпадения на первой строке
  • (*NO_AUTO_CAPTURE) - отключает автоматический захват для групп; (?<name>...) можно использовать для захвата
  • (*CR) - переводы строк разделены \r
  • (*LF) - переводы строк разделены \n (по умолчанию для UNIX)
  • (*CRLF) - переводы строк разделены \r\n (по умолчанию для Windows)
  • (*ANYCRLF) - переводы строк разделены любым из вышеперечисленных
  • (*ANY) - переводы строк разделены любым из вышеперечисленных и Unicode-переводами строк:

    отдельные символы VT (вертикальная табуляция, U+000B), FF (перевод страницы, U+000C), NEL (следующая строка, U+0085), LS (разделитель строк, U+2028) и PS (разделитель абзацев, U+2029). Для 8-битной библиотеки два последних распознаются только в режиме UTF-8. — man pcre

  • (*JAVASCRIPT_COMPAT) - совместимость с JavaScript
  • (*NO_STUDY) - отключение изучения; изучение включено по умолчанию

Для получения более подробной информации о группах параметров, см. разделы Установка параметров и Конвенция перевода строк в руководстве по синтаксису PCRE.

Некоторые из этих параметров не являются частью PCRE и преобразуются nre в флаги PCRE. К ним относятся NEVER_UTF, ANCHORED, DOLLAR_ENDONLY, FIRSTLINE, NO_AUTO_CAPTURE, JAVASCRIPT_COMPAT, U, NO_STUDY. В других обёртках PCRE вам нужно будет передавать их как отдельные флаги в PCRE.

Источник Редактировать
RegexError = ref object of CatchableError
Источник Редактировать
RegexInternalError = ref object of RegexError
Внутренняя ошибка модуля, вероятно, указывает на ошибку Источник Редактировать
RegexMatch = object
  pattern*: Regex            ## The regex doing the matching.
                             ## Not nil.
  str*: string               ## The string that was matched against.
  ## First item is the bounds of the match
  ## Other items are the captures
  ## `a` is inclusive start, `b` is exclusive end
Обычно виден как OptionRegexMatch, он представляет результат выполнения. При неудаче — none, при успехе — some.
pattern: Regex
шаблон, который сопоставляется
str: string
строка, с которой производилось сопоставление
captures[]: string
строковое значение того, что было захвачено под этим идентификатором. Если значение некорректно, поведение неопределено. Если идентификатор равен -1, возвращается всё совпадение. Если данное захват не был сопоставлен, возвращается nil. См. примеры для match.
captureBounds[]: HSlice[int, int]
получает границы заданного захвата в соответствии с теми же правилами, что и выше. Если захват не заполнен, возвращается None. Границы являются включительными. См. примеры для match.
match: string
полный текст совпадения.
matchBounds: HSlice[int, int]
границы совпадения, как и в captureBounds[]
(captureBounds|captures).toTable
возвращает таблицу с каждым именованным захватом в качестве ключа.
(captureBounds|captures).toSeq
возвращает все захваты по их номеру.
$: string
то же, что и match
Источник Редактировать
StudyError = ref object of RegexError
Выбрасывается, когда изучение регулярного выражения терпит неудачу по какой-либо причине. Сообщение содержит код ошибки. Источник Редактировать
SyntaxError = ref object of RegexError
  pos*: int                  ## the location of the syntax error in bytes
  pattern*: string           ## the pattern that caused the problem
Выбрасывается при синтаксической ошибке в строке регулярного выражения, переданной в Источник Редактировать

Процедуры

proc `$`(pattern: RegexMatch): string {....raises: [], tags: [], forbids: [].}
Исходный код Редактировать
proc `==`(a, b: Regex): bool {....raises: [], tags: [], forbids: [].}
Исходный код Редактировать
proc `==`(a, b: RegexMatch): bool {....raises: [], tags: [], forbids: [].}
Исходный код Редактировать
func `[]`(pattern: CaptureBounds; i: int): HSlice[int, int] {....raises: [],
    tags: [], forbids: [].}
Исходный код Редактировать
func `[]`(pattern: CaptureBounds; name: string): HSlice[int, int] {.
    ...raises: [KeyError], tags: [], forbids: [].}
Исходный код Редактировать
func `[]`(pattern: Captures; i: int): string {....raises: [], tags: [], forbids: [].}
Исходный код Редактировать
func `[]`(pattern: Captures; name: string): string {....raises: [KeyError],
    tags: [], forbids: [].}
Исходный код Редактировать
func captureBounds(pattern: RegexMatch): CaptureBounds {....raises: [], tags: [],
    forbids: [].}
Исходный код Редактировать
proc captureCount(pattern: Regex): int {....raises: [ValueError], tags: [],
    forbids: [].}
Исходный код Редактировать
proc captureNameId(pattern: Regex): Table[string, int] {....raises: [], tags: [],
    forbids: [].}
Исходный код Редактировать
func captures(pattern: RegexMatch): Captures {....raises: [], tags: [], forbids: [].}
Исходный код Редактировать
func contains(pattern: CaptureBounds; i: int): bool {....raises: [], tags: [],
    forbids: [].}
Исходный код Редактировать
func contains(pattern: CaptureBounds; name: string): bool {....raises: [KeyError],
    tags: [], forbids: [].}
Исходный код Редактировать
func contains(pattern: Captures; i: int): bool {....raises: [], tags: [],
    forbids: [].}
Исходный код Редактировать
func contains(pattern: Captures; name: string): bool {....raises: [KeyError],
    tags: [], forbids: [].}
Исходный код Редактировать
proc contains(str: string; pattern: Regex; start = 0; endpos = int.high): bool {.
    ...raises: [ValueError, RegexInternalError, InvalidUnicodeError], tags: [],
    forbids: [].}
Определить, содержит ли строка заданный шаблон между конечными и начальными позициями: Эта функция эквивалентна isSome(str.find(pattern, start, endpos)).

Пример:

assert "abc".contains(re"bc")
assert not "abc".contains(re"cd")
assert not "abc".contains(re"a", start = 1)
Исходный код Редактировать
proc escapeRe(str: string): string {....gcsafe, raises: [], tags: [], forbids: [].}

Экранирует строку, чтобы она не соответствовала никаким специальным символам. Несовместимо с флагом Extra (X).

Экранированный символ: \ + * ? [ ^ ] $ ( ) { } = ! < > | : -

Пример:

assert escapeRe("fly+wind") == "fly\\+wind"
assert escapeRe("!") == "\\!"
assert escapeRe("nim*") == "nim\\*"
Исходный код Редактировать
proc find(str: string; pattern: Regex; start = 0; endpos = int.high): Option[
    RegexMatch] {....raises: [ValueError, RegexInternalError, InvalidUnicodeError],
                  tags: [], forbids: [].}
Ищет заданный шаблон в строке между конечными и начальными позициями.
start
Начальная точка для начала сопоставления. |abc это 0; a|bc это 1
endpos
Максимальный индекс для сопоставления; int.high означает конец строки, в противном случае это включительная верхняя граница.
Исходный код Редактировать
proc findAll(str: string; pattern: Regex; start = 0; endpos = int.high): seq[
    string] {....raises: [ValueError, RegexInternalError, InvalidUnicodeError],
              tags: [], forbids: [].}
Исходный код Редактировать
func match(pattern: RegexMatch): string {....raises: [], tags: [], forbids: [].}
Исходный код Редактировать
proc match(str: string; pattern: Regex; start = 0; endpos = int.high): Option[
    RegexMatch] {....raises: [ValueError, RegexInternalError, InvalidUnicodeError],
                  tags: [], forbids: [].}
Подобно find(...), но закреплено в начале строки.

Пример:

assert "foo".match(re"f").isSome
assert "foo".match(re"o").isNone

assert "abc".match(re"(\w)").get.captures[0] == "a"
assert "abc".match(re"(?<letter>\w)").get.captures["letter"] == "a"
assert "abc".match(re"(\w)\w").get.captures[-1] == "ab"

assert "abc".match(re"(\w)").get.captureBounds[0] == 0 .. 0
assert 0 in "abc".match(re"(\w)").get.captureBounds
assert "abc".match(re"").get.captureBounds[-1] == 0 .. -1
assert "abc".match(re"abc").get.captureBounds[-1] == 0 .. 2
Исходный код Редактировать
func matchBounds(pattern: RegexMatch): HSlice[int, int] {....raises: [], tags: [],
    forbids: [].}
Исходный код Редактировать
proc re(pattern: string): Regex {....raises: [KeyError, SyntaxError, StudyError,
    ValueError], tags: [], forbids: [].}
Исходный код Редактировать
proc replace(str: string; pattern: Regex; sub: string): string {.
    ...raises: [ValueError, RegexInternalError, InvalidUnicodeError, KeyError],
    tags: [], forbids: [].}
Исходный код Редактировать
proc replace(str: string; pattern: Regex;
             subproc: proc (match: RegexMatch): string): string {.
    ...raises: [ValueError, RegexInternalError, InvalidUnicodeError, Exception],
    tags: [RootEffect], forbids: [].}

Заменяет каждый совпадение Regex в строке на subproc, которое никогда не должно быть или возвращать nil.

Если subproc является процедурой proc (RegexMatch): string, то она выполняется с каждым совпадением, а возвращаемое значение является значением замены.

Если subproc является процедурой proc (string): string, то она выполняется со всем текстом совпадения, а возвращаемое значение является значением замены.

Если subproc является строкой, синтаксис следующий:

  • $$ - буквальное значение $
  • $123 - номер захвата 123
  • $foo - именованный захват foo
  • ${foo} - то же самое, что выше
  • $1$# - первый и второй захваты
  • $# - первый захват
  • $0 - полное совпадение

Если указанный захват отсутствует, выбрасывается исключение IndexDefect для неуказанных захватов и KeyError для именованных захватов.

Исходный код Редактировать
proc replace(str: string; pattern: Regex; subproc: proc (match: string): string): string {.
    ...raises: [ValueError, RegexInternalError, InvalidUnicodeError, Exception],
    tags: [RootEffect], forbids: [].}
Исходный код Редактировать
proc split(str: string; pattern: Regex; maxSplit = -1; start = 0): seq[string] {.
    ...raises: [ValueError, RegexInternalError, InvalidUnicodeError], tags: [],
    forbids: [].}

Разделяет строку с помощью заданного регулярного выражения. Это работает в соответствии с правилами, используемыми Perl и Javascript.

start ведет себя так же, как в find(...).

Пример:

# -  If the match is zero-width, then the string is still split:
assert "123".split(re"") == @["1", "2", "3"]

# -  If the pattern has a capture in it, it is added after the string
#    split:
assert "12".split(re"(\d)") == @["", "1", "", "2", ""]

# -  If `maxsplit != -1`, then the string will only be split
#    `maxsplit - 1` times. This means that there will be `maxsplit`
#    strings in the output seq.
assert "1.2.3".split(re"\.", maxsplit = 2) == @["1", "2.3"]
Исходный код Редактировать
proc toSeq(pattern: CaptureBounds; default = none(HSlice[int, int])): seq[
    Option[HSlice[int, int]]] {....raises: [ValueError], tags: [], forbids: [].}
Исходный код Редактировать
proc toSeq(pattern: Captures; default: Option[string] = none(string)): seq[
    Option[string]] {....raises: [ValueError], tags: [], forbids: [].}
Исходный код Редактировать
func toTable(pattern: CaptureBounds): Table[string, HSlice[int, int]] {.
    ...raises: [KeyError], tags: [], forbids: [].}
Исходный код Редактировать
func toTable(pattern: Captures): Table[string, string] {....raises: [KeyError],
    tags: [], forbids: [].}
Исходный код Редактировать

Итераторы

iterator findIter(str: string; pattern: Regex; start = 0; endpos = int.high): RegexMatch {.
    ...raises: [ValueError, RegexInternalError, InvalidUnicodeError], tags: [],
    forbids: [].}
Работает так же, как find(...), но находит все неперекрывающиеся совпадения:

Пример:

import std/sugar
assert collect(for a in "2222".findIter(re"22"): a.match) == @["22", "22"]
 # not @["22", "22", "22"]

Аргументы такие же, как у find(...)

Варианты:

  • proc findAll(...) возвращает seq[string]
Исходный код Редактировать
iterator items(pattern: CaptureBounds; default = none(HSlice[int, int])): Option[
    HSlice[int, int]] {....raises: [ValueError], tags: [], forbids: [].}
Исходный код Редактировать
iterator items(pattern: Captures; default: Option[string] = none(string)): Option[
    string] {....raises: [ValueError], tags: [], forbids: [].}
Исходный код Редактировать

© 2006–2024 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/nre.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API