示例

快速简易的 semver

import { char, createRegExp, digit, maybe, oneOrMore } from 'magic-regexp'

createRegExp(
  oneOrMore(digit).groupedAs('major'),
  '.',
  oneOrMore(digit).groupedAs('minor'),
  maybe('.', oneOrMore(char).groupedAs('patch'))
)
// /(?<major>\d+)\.(?<minor>\d+)(?:\.(?<patch>.+))?/

使用组名引用先前捕获的组

import assert from 'node:assert'
import { char, createRegExp, oneOrMore, wordChar } from 'magic-regexp'

const TENET_RE = createRegExp(
  wordChar
    .groupedAs('firstChar')
    .and(wordChar.groupedAs('secondChar'))
    .and(oneOrMore(char))
    .and(referenceTo('secondChar'))
    .and(referenceTo('firstChar'))
)
// /(?<firstChar>\w)(?<secondChar>\w).+\k<secondChar>\k<firstChar>/

assert.equal(TENET_RE.test('TEN<==O==>NET'), true)

类型级 RegExp 匹配和替换结果(实验性)

当使用如 magic-regexp v3.2.5.beta.1 just release! 这样的字面字符串进行匹配或替换时

import {
  anyOf,
  createRegExp,
  digit,
  exactly,
  oneOrMore,
  wordChar
} from 'magic-regexp/further-magic'

const literalString = 'magic-regexp 3.2.5.beta.1 just release!'

const semverRegExp = createRegExp(
  oneOrMore(digit)
    .as('major')
    .and('.')
    .and(oneOrMore(digit).as('minor'))
    .and(
      exactly('.')
        .and(oneOrMore(anyOf(wordChar, '.')).groupedAs('patch'))
        .optionally()
    )
)

// `String.match()` 示例
const matchResult = literalString.match(semverRegExp)
matchResult[0] // "3.2.5.beta.1"
matchResult[3] // "5.beta.1"
matchResult.length // 4
matchResult.index // 14
matchResult.groups
//   groups: {
//     major: "3";
//     minor: "2";
//     patch: "5.beta.1";
//  }

// `String.replace()` 示例
const replaceResult = literalString.replace(
  semverRegExp,
  `minor version "$2" brings many great DX improvements, while patch "$<patch>" fix some bugs and it's`
)

replaceResult // "magic-regexp minor version \"2\" brings many great DX improvements, while patch \"5.beta.1\" fix some bugs and it's just release!"

当匹配动态字符串时,结果将是可能匹配的并集

const myString = 'dynamic'

const RegExp = createRegExp(exactly('foo').or('bar').groupedAs('g1'))
const matchAllResult = myString.match(RegExp)

matchAllResult
// null | RegExpMatchResult<{
//     matched: ["bar", "bar"] | ["foo", "foo"];
//     namedCaptures: ["g1", "bar"] | ["g1", "foo"];
//     input: string;
//     restInput: undefined;
// }>
matchAllResult?.[0] // ['foo', 'foo'] | ['bar', 'bar']
matchAllResult?.length // 2 | undefined
matchAllResult?.groups
// groups: {
//     g1: "foo" | "bar";
// } | undefined