Vytváření gramatických regexů pomocí XRegExp.build

Nedávno jsem přidal tři nové doplňky pro XRegExp v2.0 (momentálně ve fázi kandidátů na vydání na GitHubu):

  • XRegExp.build — Umožňuje vytvářet regulární výrazy pomocí pojmenovaných dílčích vzorů. Inspirováno RegExp.create od Lea Verou.
  • Metody prototypu XRegExp — Přidá kolekci metod, které mají být zděděny regexy XRegExp:apply , call , forEach , globalize , xexec a xtest . Tyto také fungují pro nativní RegExp zkopírované XRegExp.
  • Vlastnosti XRegExp Unicode — Zahrnuje zbývajících devět vlastností (nad rámec toho, co je již k dispozici v jiných XRegExp addonech) požadovaných pro podporu Unicode úrovně 1:Alphabetic , Uppercase , Lowercase , White_Space , Noncharacter_Code_Point , Default_Ignorable_Code_Point , Any , ASCII a Assigned .

Přeskočíme-li přímo do nějakého kódu, následující ukázka ukazuje, jak lze nový doplněk XRegExp.build použít k vytvoření gramatického vzoru pro párování reálných čísel:

// Approach 1: Make all of the subpatterns reusable

var lib = {
    digit:             /[0-9]/,
    exponentIndicator: /[Ee]/,
    digitSeparator:    /[_,]/,
    sign:              /[+-]/,
    point:             /[.]/
};
lib.preexponent = XRegExp.build('(?xn)\
    {{sign}} ?              \
    (?= {{digit}}           \
      | {{point}}           \
    )                       \
    ( {{digit}} {1,3}       \
      ( {{digitSeparator}} ?\
        {{digit}} {3}       \
      ) *                   \
    ) ?                     \
    ( {{point}}             \
      {{digit}} +           \
    ) ?                     ',
    lib
);
lib.exponent = XRegExp.build('(?x)\
    {{exponentIndicator}}\
    {{sign}} ?           \
    {{digit}} +          ',
    lib
);
lib.real = XRegExp.build('(?x)\
    ^              \
    {{preexponent}}\
    {{exponent}} ? \
    $              ',
    lib
);

// Approach 2: No need to reuse the subpatterns. {{sign}} and {{digit}} are
// defined twice, but that can be avoided by defining them before constructing
// the main pattern (see Approach 1).

var real = XRegExp.build('(?x)\
    ^              \
    {{preexponent}}\
    {{exponent}} ? \
    $              ',
    {
        preexponent: XRegExp.build('(?xn)\
            {{sign}} ?              \
            (?= {{digit}}           \
              | {{point}}           \
            )                       \
            ( {{digit}} {1,3}       \
              ( {{digitSeparator}} ?\
                {{digit}} {3}       \
              ) *                   \
            ) ?                     \
            ( {{point}}             \
              {{digit}} +           \
            ) ?                     ',
            {
                sign:           /[+-]/,
                digit:          /[0-9]/,
                digitSeparator: /[_,]/,
                point:          /[.]/
            }
        ),
        exponent: XRegExp.build('(?x)\
            {{exponentIndicator}}\
            {{sign}} ?           \
            {{digit}} +          ',
            {
                sign:              /[+-]/,
                digit:             /[0-9]/,
                exponentIndicator: /[Ee]/
            }
        )
    }
);

real a lib.real regexy vytvořené výše uvedeným kódem jsou identické. Zde je několik příkladů řetězců, kterým odpovídají:

  • -1
  • 1,000
  • 10_000_000
  • 1,111.1111
  • 01.0
  • .1
  • 1e2
  • +1.1e-2

A zde je několik příkladů řetězců, které se neshodují:

  • ,100
  • 10,00
  • 1,0000
  • 1.
  • 1.1,111
  • 1k

Gramatické vzorce, jako je tento, se snáze čtou, zapisují a udržují a vypadají spíše jako BNF než typické regulární výrazy se šumem v řádcích, které někteří lidé nenávidí.

Všimněte si, že {{…}} zde zobrazená syntaxe funguje pouze pro regulární výrazy vytvořené XRegExp.build . Pojmenované podvzory mohou být poskytnuty jako řetězce nebo objekty regulárních výrazů (řetězce jsou předány do XRegExp konstruktér). Poskytnuté vzory jsou automaticky zabaleny do (?:…) takže je lze kvantifikovat jako jednotku a neočekávaným způsobem nezasahují do okolního vzoru. Přední ^ a na konci neuvedených $ jsou odstraněny z dílčích vzorů, pokud jsou přítomny oba, což umožňuje vkládání nezávisle užitečných ukotvených vzorů. Příznaky lze poskytnout prostřednictvím XRegExp.build 's volitelný třetí (flags ) argument. Nativní příznaky používané zadanými dílčími vzory jsou ignorovány ve prospěch flags argument. Zpětné odkazy ve vnějším vzoru a poskytnutých dílčích vzorech se automaticky přečíslují, aby správně fungovaly v rámci většího kombinovaného vzoru. Syntaxe ({{name}}) funguje jako zkratka pro pojmenované zachycení přes (?<name>{{name}}) . {{…}} syntaxi lze escapovat zpětným lomítkem.

Trochu si pohrajte s výše uvedenými detaily a myslím, že zjistíte, že XRegExp.build funguje intuitivně a poradí si se všemi hraničními případy, které na něj hodíte.

Neváhejte se podělit o to, jak byste mohli změnit výše uvedené regulární výrazy. A nezapomeňte se podívat na luxusní nový XRegExp v2.0 a jeho upgradované doplňky na GitHubu.