Skip to content

Naming a Unicode property: \p{...}

One line: \p{...} asks a question about a character — is it a letter (\p{L}), is it Greek (\p{Greek}), is it alphabetic (\p{Alphabetic}) — instead of listing the characters you hope are; the engines do not disagree about what Greek is, they disagree about how to spell it, and two of them accept a misspelling without a word.

Level: 301 · you write patterns against names, amounts and free text that are not only ASCII

Keywords on this page: \p{…} · \X · [[:alpha:]] · […] — Topics: Unicode text

What it replaces

[A-Za-z] is a list. \p{L} is a question the engine answers from the Unicode Character Database it already ships. The list has 52 entries and is wrong for most of the world's names; the question is right by construction and stays right when the table is updated.

You mean The list you probably wrote The property
a letter [A-Za-z] \p{L}
a decimal digit [0-9] \p{Nd}
an uppercase letter [A-Z] \p{Lu}
punctuation [.,;:!?-] \p{P}
whitespace [ \t] \p{White_Space}

The rest of this page is about which of those the engine in front of you accepts, and what it does with the ones it accepts but does not understand.

The three things a property can name

Perl has the fullest and plainest spelling, so it is the clearest place to see all three kinds at once. Every character below is written and reported as a code point, never printed: an answer key that printed GREEK SMALL LETTER ALPHA would depend on the terminal, the locale and the runtime's build. The cast is deliberately boring — Latin, Greek, Cyrillic, Han, two digits, two spaces and a dash — because every one of those has had the same general category and the same script since the 1990s, and a key built on a character whose classification moved recently would differ between Perl 5.38 and 5.42, or between Python 3.12 and 3.14.

Verified output of property_kinds_pl.pl — regenerated by tools/run_examples.py, never hand-typed.

the cast
  0009  CHARACTER TABULATION
  0037  DIGIT SEVEN
  0041  LATIN CAPITAL LETTER A
  00A0  NO-BREAK SPACE
  00E9  LATIN SMALL LETTER E WITH ACUTE
  03B1  GREEK SMALL LETTER ALPHA
  0394  GREEK CAPITAL LETTER DELTA
  0416  CYRILLIC CAPITAL LETTER ZHE
  0660  ARABIC-INDIC DIGIT ZERO
  2014  EM DASH
  4E2D  CJK UNIFIED IDEOGRAPH-4E2D

general category -- what KIND of character it is
  \p{L}                   0041 00E9 03B1 0394 0416 4E2D
  \p{Lu}                  0041 0394 0416
  \p{Ll}                  00E9 03B1
  \p{Lo}                  4E2D
  \p{Nd}                  0037 0660
  \p{Zs}                  00A0
  \p{P}                   2014
  \P{L}                   0009 0037 00A0 0660 2014

script -- what WRITING SYSTEM it belongs to
  \p{Greek}               03B1 0394
  \p{Cyrillic}            0416
  \p{Script=Han}          4E2D
  \p{Latin}               0041 00E9

binary property -- one yes/no fact the standard records
  \p{Alphabetic}          0041 00E9 03B1 0394 0416 4E2D
  \p{Uppercase}           0041 0394 0416
  \p{White_Space}         0009 00A0

composed inside a character class
  [\p{L}\p{Nd}]           0037 0041 00E9 03B1 0394 0416 0660 4E2D
  [\p{Greek}\p{Cyrillic}] 03B1 0394 0416
  [^\p{L}]                0009 0037 00A0 0660 2014

grapheme clusters in U+0065 U+0301
  \X                      1
  .                       2

Four things to take from that run.

A general category is what kind of character it is. One letter is the union (\p{L} took all six letters), two letters is the subdivision (\p{Lu} took the three uppercase ones, \p{Lo} took only U+4E2D). Every character has exactly one.

A script is what writing system it belongs to. \p{Greek} took U+03B1 and U+0394 and left U+4E2D alone. A script is not "foreign" and not "non-ASCII" — U+0041 LATIN CAPITAL LETTER A is \p{Latin}, and so is U+00E9.

A binary property is one yes/no fact, on a different axis from the category. Look at the two whitespace rows: \p{Zs} took only U+00A0, while \p{White_Space} took U+0009 CHARACTER TABULATION as well. Tab's general category is Cc, a control character; the standard separately records that it is whitespace. A binary property is not a coarser category, it is a different question.

\P{...} is the negation and a class composes them. Capital P inverts — \P{L} picked up exactly the five non-letters. Inside [...] several properties union, and [^\p{L}] is the same set as \P{L}.

Who has it, and under what spelling

Verified output of property_spellings_sh.sh — regenerated by tools/run_examples.py, never hand-typed.

does it COMPILE?             python  perl   node u  ruby   java   go
\p{L}                        no      yes    yes     yes    yes    yes
\pL                          no      yes    no      yes    yes    yes
\p{Lu}                       no      yes    yes     yes    yes    yes
\p{Nd}                       no      yes    yes     yes    yes    yes
\p{P}                        no      yes    yes     yes    yes    yes
\p{Greek}                    no      yes    no      yes    no     yes
\p{Script=Greek}             no      yes    yes     no     yes    no
\p{sc=Greek}                 no      yes    yes     no     yes    no
\p{IsGreek}                  no      yes    no      no     yes    no
\p{Alphabetic}               no      yes    yes     yes    no     no
\p{IsAlphabetic}             no      yes    no      no     yes    no
\p{White_Space}              no      yes    yes     yes    no     no
\p{Alpha}                    no      yes    yes     yes    yes    no
[\p{L}\p{Nd}]                no      yes    yes     yes    yes    yes
\X                           no      yes    no      yes    yes    no

and where it compiles, does it MEAN what it says?
(the two answers are U+0041 and U+03B1; a dash is: did not compile)
spelling       python    perl      node u    ruby      java      go
\pL            - -       yes yes   - -       no no     yes yes   yes yes
\p{Alpha}      - -       yes yes   yes yes   yes yes   yes no    - -
\p{Greek}      - -       no yes    - -       no yes    - -       no yes

compiled, but ruby warned while doing it:
  \pL

and what go calls a property it has never heard of:
  invalid character class range
  invalid escape sequence

The general category rows are the only ones where everybody agrees: \p{L}, \p{Lu}, \p{Nd}, \p{P} compile in all five engines that have properties at all. Below that, three stripes:

  • The bare script name \p{Greek} — Perl, Ruby and Go take it; Java and JavaScript refuse it.
  • The Script= form — Perl, JavaScript and Java take it; Ruby and Go refuse it.
  • Perl's Is prefix — Perl and Java take it, and no one else; PCRE2 refuses it too, which is the divergence that matters most and is measured further down.

Binary properties are where Go stops. \p{Alphabetic} and \p{White_Space} compile in Perl, JavaScript and Ruby, need the Is prefix in Java, and do not exist in Go's regexp at all. The last block is what Go says about them: invalid character class range, which does not sound like "I have never heard of that property" but is what it means, and invalid escape sequence for \X. Neither message names a property, so a reader who does not already know tends to go looking for a typo in the brackets.

The second table is the more important one, because compiling is not understanding:

  • Ruby accepts \pL and means the literal text pL. It matched neither U+0041 nor U+03B1. Ruby does warn while compiling it, and the third block is that warning — captured as a flag rather than as a message, because the message carries a file name and a line number. JavaScript under u refuses \pL outright; Perl, Java and Go read it as \p{L}, which is what it was meant to be.
  • \p{Alpha} compiles in four engines and means two different things. Perl, JavaScript and Ruby read it as the Unicode binary property Alphabetic and match U+03B1. Java reads it as the POSIX class over US-ASCII and does not.

Two silent failures

Python's re has no properties at all — and refuses to pretend

Verified output of property_absent_py.py — regenerated by tools/run_examples.py, never hand-typed.

re, asked for a Unicode property
  \p{L}      re.error: bad escape \p at position 0
  \P{L}      re.error: bad escape \P at position 0
  [\p{L}]    re.error: bad escape \p at position 1
  \pL        re.error: bad escape \p at position 0
  \p{Greek}  re.error: bad escape \p at position 0

what the standard library offers instead
  code point  isalpha()  isdecimal()  category
  0009        False      False        Cc
  0037        False      True         Nd
  0041        True       False        Lu
  00A0        False      False        Zs
  00E9        True       False        Ll
  03B1        True       False        Ll
  0394        True       False        Lu
  0416        True       False        Lu
  0660        False      True         Nd
  2014        False      False        Pd
  4E2D        True       False        Lo

one script, spelled as an explicit range
  [U+0370-U+03FF] matches: 03B1 0394

bad escape \p at position 0 arrives from re.compile, with no subject in sight, and it is the same message on Python 3.12 and 3.14. That is the good outcome: a pattern lifted out of a Perl or PCRE codebase fails on the line that compiles it, not six months later on the one customer whose name is Greek. It is the same kindness Python shows for forward references.

What to reach for instead, in order of how close it stays to the original pattern:

  1. The third-party regex module, which is a drop-in replacement for re and does have \p{...}. Nothing on this page uses it, because a lesson whose examples need an install is teaching something the reader's interpreter cannot do.
  2. The str predicates and unicodedata. In the table above, isalpha() is True on exactly the characters whose category begins with L, and isdecimal() on exactly the two whose category is Nd — so they stand in for \p{L} and \p{Nd} respectively, not for the binary properties of the same name. unicodedata.category() hands you the two-letter category itself, which turns a general-category test into a comparison rather than a pattern.
  3. An explicit range, which is exact when you can name the block and wrong the moment a script spills outside one. [U+0370-U+03FF] caught both Greek letters in the cast, and would miss every polytonic Greek letter in U+1F00..U+1FFF. A block is not a script; the range is a stand-in, not a translation.

JavaScript needs the u flag, and says nothing without it

Verified output of property_u_flag_js.js — regenerated by tools/run_examples.py, never hand-typed.

without the u flag, \p is the letter p
  /^\p{L}$/ on the 4-character text p{L}    true
  /^\p{L}$/ on U+03B1                       false
  /^\P{L}$/ on the 4-character text P{L}    true

with the u flag, does it compile?
  \p{L}                       compiles
  \pL                         refused
  \p{Lu}                      compiles
  \p{Nd}                      compiles
  \p{P}                       compiles
  \p{Greek}                   refused
  \p{Script=Greek}            compiles
  \p{sc=Greek}                compiles
  \p{Script_Extensions=Greek} compiles
  \p{Alphabetic}              compiles
  \p{Alpha}                   compiles
  \p{White_Space}             compiles
  \p{gc=Lu}                   compiles
  [\p{L}\p{Nd}]               compiles
  \X                          refused

and what the ones that compile match
  \p{L}                       0041 00E9 03B1 0394 0416 4E2D
  \p{Lu}                      0041 0394 0416
  \p{Nd}                      0037 0660
  \p{P}                       2014
  \p{Script=Greek}            03B1 0394
  \p{sc=Greek}                03B1 0394
  \p{Script_Extensions=Greek} 03B1 0394
  \p{Alphabetic}              0041 00E9 03B1 0394 0416 4E2D
  \p{Alpha}                   0041 00E9 03B1 0394 0416 4E2D
  \p{White_Space}             0009 00A0
  \p{gc=Lu}                   0041 0394 0416
  [\p{L}\p{Nd}]               0037 0041 00E9 03B1 0394 0416 0660 4E2D

/^\p{L}$/ matched the four-character text p{L} and did not match U+03B1. In a legacy (non-u) pattern, Annex B's identity-escape rule turns \p into the plain letter p, and {L} is not a valid quantifier so it stays literal too. Nothing warns. A pattern written from Perl habits, tested against ASCII, passes review, ships, and quietly never matches a Greek name.

With the flag, properties are ES2018 and the rules tighten: \pL without braces is refused, \p{Greek} is refused because JavaScript wants scripts spelled \p{Script=Greek} or \p{sc=Greek}, and \p{Alpha} is accepted as an alias for the binary property Alphabetic — so it matches U+03B1, which is the exact opposite of what that same spelling means in Java.

ES2024's v flag adds set operations inside a class and properties of strings. This page does not probe it: the answer key has to hold on both node versions this library runs against, and v is not in the older one.

Java: the same syntax, a different dictionary

Verified output of property_posix_alpha_java.java — regenerated by tools/run_examples.py, never hand-typed.

general category: the one spelling everybody agrees on
  \p{L}                 0041 00E9 03B1 0394 0416 4E2D
  \pL                   0041 00E9 03B1 0394 0416 4E2D
  \p{Lu}                0041 0394 0416
  \p{Nd}                0037 0660
  \p{P}                 2014

script: Java wants Is, or script=, and refuses the bare name
  \p{Greek}             refused: Unknown character property name {Greek}
  \p{IsGreek}           03B1 0394
  \p{script=Greek}      03B1 0394
  \p{sc=Greek}          03B1 0394
  \p{InGreek}           03B1 0394
  \p{IsHan}             4E2D

binary property: Is again
  \p{Alphabetic}        refused: Unknown character property name {Alphabetic}
  \p{IsAlphabetic}      0041 00E9 03B1 0394 0416 4E2D
  \p{White_Space}       refused: Unknown character property name {White_Space}
  \p{IsWhite_Space}     0009 00A0
  \p{gc=Lu}             0041 0394 0416

the POSIX names -- same syntax, US-ASCII meaning
  \p{Alpha}             0041
  \p{Digit}             0037
  \p{Upper}             0041
  \p{Punct}             (nothing)

the same POSIX names under UNICODE_CHARACTER_CLASS, or inline (?U)
  \p{Alpha}             0041 00E9 03B1 0394 0416 4E2D
  \p{Digit}             0037 0660
  \p{Upper}             0041 0394 0416
  \p{Punct}             2014

grapheme clusters in U+0065 U+0301
  \X                    1
  .                     2

Java refuses \p{Greek} outright — Unknown character property name {Greek} — and wants \p{IsGreek}, \p{script=Greek} or \p{sc=Greek}. The same Is is needed for binary properties: \p{Alphabetic} is an error and \p{IsAlphabetic} is not. \p{InGreek} compiles too, and it is a block rather than a script: a block is a contiguous range of code points, a script is a property carried by each character. They agree on this cast and they part company as soon as a script spills out of its block, which is the same trap as the explicit range Python was left with above.

Then the collision this section exists for. \p{Alpha}, \p{Digit}, \p{Upper} and \p{Punct} are POSIX classes defined over US-ASCII. \p{Alpha} matched U+0041 and nothing else. \p{Punct} matched nothing at all, because EM DASH is not ASCII punctuation. Identical syntax to a Unicode property, a completely different meaning, no diagnostic — and a reviewer who knows Perl will read it as the Unicode one. Pattern.UNICODE_CHARACTER_CLASS, or inline (?U), re-points all four at Unicode, and the block after it measures exactly that.

Rust's regex accepts every spelling

Verified output of property_sets_rs_sh.sh — regenerated by tools/run_examples.py, never hand-typed.

general category
  \p{L}                         0041 00E9 03B1 0394 0416 4E2D
  \pL                           0041 00E9 03B1 0394 0416 4E2D
  \p{Lu}                        0041 0394 0416
  \p{Nd}                        0037 0660
  \p{Zs}                        00A0
  \p{P}                         2014
  \P{L}                         0009 0037 00A0 0660 2014

script -- every spelling this page has met
  \p{Greek}                     03B1 0394
  \p{Script=Greek}              03B1 0394
  \p{sc=Greek}                  03B1 0394
  \p{IsGreek}                   03B1 0394
  \p{Script_Extensions=Greek}   03B1 0394
  \p{Han}                       4E2D

binary property
  \p{Alphabetic}                0041 00E9 03B1 0394 0416 4E2D
  \p{Uppercase}                 0041 0394 0416
  \p{White_Space}               0009 00A0
  \p{Alpha}                     0041 00E9 03B1 0394 0416 4E2D
  \p{Any}                       0009 0037 0041 00A0 00E9 03B1 0394 0416 0660 2014 4E2D

set operations inside a class -- regex alone among these engines
  [\p{L}\p{Nd}]                 0037 0041 00E9 03B1 0394 0416 0660 4E2D
  [\p{Greek}&&\p{Lu}]           0394
  [\p{L}--\p{Greek}]            0041 00E9 0416 4E2D
  [\p{Greek}~~\p{Lu}]           0041 03B1 0416

no grapheme cluster escape in either crate
  regex        error: unrecognized escape sequence
  fancy-regex  Parsing error at position 0: Invalid escape: \X

regex is the most complete property implementation this library measures. Every script spelling this page has met compiles, and they all agree — the bare name, Script=, sc=, Perl's Is, and Script_Extensions= besides. Binary properties are there, \p{Alpha} means the Unicode one, and \p{Any} is every code point.

It is also the only engine here whose ordinary character class does set operations: [\p{Greek}&&\p{Lu}] intersected down to U+0394 alone, [\p{L}--\p{Greek}] subtracted the Greek letters out, and [\p{Greek}~~\p{Lu}] took the symmetric difference — every Greek or uppercase character that is not both. Perl reaches the same place with a separate construct, (?[ ... ]), and JavaScript's v flag adds one too; neither is measured on this page.

What regex does not have is \X, and neither does fancy-regex.

PCRE2 — and therefore ABAP

ABAP's PCRE addition is the PCRE2 library in the kernel, so PCRE2's answers are ABAP's answers. Each file below holds exactly one character, so that pcre2grep -l prints which characters matched using only ASCII:

Real run — PCRE2 10.48 (pcre2grep), macOS 26.6.2 x86-64, 2026-09-22. Each U_XXXX.txt contains the single character U+XXXX and nothing else.

$ pcre2grep -u -l '\p{Greek}' U_*.txt
U_0394.txt
U_03B1.txt
$ pcre2grep -u -l '\p{Script=Greek}' U_*.txt
U_0394.txt
U_03B1.txt
$ pcre2grep -u -l '\p{IsGreek}' U_*.txt
pcre2grep: Error in command-line regex at offset 11: unknown property after \P or \p
$ pcre2grep -u -l '\p{Alphabetic}' U_*.txt
U_0041.txt
U_00E9.txt
U_0394.txt
U_03B1.txt
U_0416.txt
U_4E2D.txt
$ pcre2grep -u -l '\p{Alpha}' U_*.txt
U_0041.txt
U_00E9.txt
U_0394.txt
U_03B1.txt
U_0416.txt
U_4E2D.txt
$ pcre2grep -u -l '\p{Nd}' U_*.txt
U_0037.txt
U_0660.txt
$ printf 'e\xcc\x81\n' > combining.txt
$ pcre2grep -u -o '\X' combining.txt | wc -l
       1
$ pcre2grep -u -o '.' combining.txt | wc -l
       2

The last three commands are the grapheme-cluster question again: combining.txt holds U+0065 LATIN SMALL LETTER E followed by U+0301 COMBINING ACUTE ACCENT, and PCRE2 counts two dots and one \X, exactly as Perl and Java did.

PCRE2 takes the bare script name and the Script= form, has the binary properties, and reads \p{Alpha} as the Unicode one — so ABAP agrees with Perl, Ruby, JavaScript and Rust on that spelling, and disagrees with Java. It does not take Perl's Is prefix — and that is the single most likely spelling to arrive in an ABAP program, because it arrives by being copied out of Perl, where it works. \p{IsGreek} compiles in Perl, compiles in Java, and is a runtime error in ABAP.

z_unicode_property.prog.abap in full — pasted here by tools/run_examples.py from the file CI runs.

REPORT z_unicode_property.

" Unicode properties in ABAP, through the PCRE addition available as of 7.55.
" Nothing in this repository can run ABAP, so this file is checked by abaplint
" and printed here as source only -- there is no recorded output beside it.
"
" ABAP does not have a regex engine of its own: the PCRE addition hands the
" pattern to the PCRE2 library in the kernel. So the answers are PCRE2's, and
" a `pcre2grep` on any machine predicts them. The page beside this file records
" one such run.

DATA(amount) = `1234`.
DATA(name)   = `Andreas`.

" A numeric field. \p{Nd} is every DECIMAL DIGIT in every script, so this
" accepts U+0660 ARABIC-INDIC DIGIT ZERO as readily as U+0037 DIGIT SEVEN --
" which is very probably not what a posting amount should accept. [0-9] is
" the honest pattern for a field that a numeric conversion has to survive.
IF matches( val = amount pcre = `\A[0-9]+\z` ).
  WRITE / `amount is ASCII digits only`.
ENDIF.

IF matches( val = amount pcre = `\A\p{Nd}+\z` ).
  WRITE / `amount is decimal digits in some script -- not the same test`.
ENDIF.

" A name field. \p{L} is every letter in every script; [A-Za-z] is a rule that
" rejects half of the customer master.
IF matches( val = name pcre = `\A[\p{L}\p{Zs}'-]+\z` ).
  WRITE / `name is letters, spaces, apostrophe and hyphen`.
ENDIF.

" Scripts. PCRE2 takes the bare name and the Script= form. It does NOT take
" Perl's Is prefix: `\p{IsGreek}` is "unknown property after \P or \p" in
" PCRE2 10.48, which is the single spelling most likely to arrive in a pattern
" copied out of a Perl program.
FIND ALL OCCURRENCES OF PCRE `\p{Greek}+` IN name RESULTS DATA(greek).
FIND ALL OCCURRENCES OF PCRE `\p{Script=Han}+` IN name RESULTS DATA(han).

" \X is one grapheme cluster: what a user calls one character, however many
" code points it takes. A truncation to a fixed length that counts with . or
" with strlen can cut a combining mark away from its base letter; counting
" with \X cannot.
FIND ALL OCCURRENCES OF PCRE `\X` IN name RESULTS DATA(graphemes).

WRITE / |{ lines( greek ) } greek runs, { lines( han ) } han runs, { lines( graphemes ) } graphemes|.

" CL_ABAP_REGEX=>CREATE_PCRE( ) and CL_ABAP_MATCHER are the object-oriented
" way in, and they take the same property syntax, because it is the same
" library underneath.

What it buys you

A numeric field. \p{Nd} matched U+0037 DIGIT SEVEN and U+0660 ARABIC-INDIC DIGIT ZERO. That is the correct reading of "a decimal digit", and it is very often not the requirement: [0-9] says "a digit the parser behind this field will certainly accept". They are different questions and the pattern should say which one you meant.

A name field. \p{L} took all six letters in the cast; [A-Za-z] would have taken U+0041 alone — not even U+00E9 LATIN SMALL LETTER E WITH ACUTE, which is Latin. A validation rule of [A-Za-z' -]+ on a customer name does not reject foreign alphabets, it rejects accents, and the rows it rejects are the ones a support ticket gets opened about.

\p{Lu} is not "uppercase". It matched U+0041, U+0394 and U+0416 — and not U+4E2D, whose category is Lo because Han has no case at all. A rule that says "the first letter must be \p{Lu}" does not mean "capitalised" in a caseless script; it means "rejected". If what you want is "starts with a letter", \p{L} is the test. The same trap runs the other way for \p{Ll}.

\X, briefly

\X matches one grapheme cluster — one character as a person counts them, however many code points that takes. U+0065 LATIN SMALL LETTER E followed by U+0301 COMBINING ACUTE ACCENT is two code points and one thing on the page: . matched 2 and \X matched 1, in Perl, in Java and in PCRE2. JavaScript, Go, Rust's regex and Python's re have no \X; Ruby does.

That is as far as this page goes, because "what counts as one character" is a question about text encoding rather than about patterns, and it has a library of its own: Encodings learning library ↗.

The measured summary

Every cell not marked otherwise comes from a block above.

Engine \p{L} Script spelled Binary property \p{Alpha} means \X Set ops in a class
Perl 5.38+ yes \p{Greek}, \p{Script=Greek}, \p{IsGreek} yes Unicode yes (?[ ... ]), not measured here
PCRE2 10.48 / ABAP PCRE yes \p{Greek}, \p{Script=Greek} — not Is yes Unicode yes no
Java 25 yes \p{IsGreek}, \p{sc=Greek} — not \p{Greek} Is prefix only US-ASCII yes no
Ruby 3.4+ yes \p{Greek} — not Script= yes Unicode yes no
JavaScript, u flag yes \p{Script=Greek} — not \p{Greek} yes Unicode no v flag, not measured here
Go regexp yes \p{Greek} — not Script= none refused no no
Rust regex yes every spelling on this page yes Unicode no yes — &&, --, ~~
Python re no — bad escape \p — — — no —
JavaScript, no u flag silently the literal p{L} — — — — —

Sort those nine rows by how the failure arrives and the ordering is the useful one. Python's is a compile error you cannot miss. Go's and Java's are compile errors whose wording does not say "property". Ruby's \pL is a warning on a pattern that then matches nothing. And the last row does not fail at all: it compiles, it runs, and it matches the wrong thing for as long as nobody types a non-ASCII letter into the field.

See also

  • What \w and \b match — the same Unicode question asked of the shorthands you already use, where the default is ASCII more often than you would guess.
  • Unicode — the chapter these two lessons belong to.
  • Who supports what — the same measured-by-compiling method over eleven other constructs, and where each engine's family is described.
  • Forward references — the other page in this library about one pattern that compiles everywhere and means different things.
  • Resources — where each engine documents itself.
  • perluniprops ↗ — the full list of property names Perl accepts, including every Is alias.
  • PCRE2 pattern syntax ↗ — the properties ABAP inherits, and the ones it does not.
  • java.util.regex.Pattern ↗ — the table where the POSIX classes and the Unicode properties sit next to each other under the same syntax.
  • Unicode support in the regex crate ↗ — the spellings, the set operations, and what the unicode feature flags cost in binary size.
  • Go regexp/syntax ↗ — the short list of what RE2 supports, which is where the missing binary properties are documented by absence.
  • Unicode Technical Standard #18 ↗ — the standard that defines what a conformant engine should call these things.