\d, \w, \s — and \h, \v, \R, \N, which only some engines have¶
One line: \d, \w and \s exist everywhere and mean ASCII in four of these eight engines and Unicode in the other four; \h (horizontal space), \R (any line break) and \N (not a newline) are Perl/PCRE2 additions that Java and Ruby partly adopted, and that JavaScript accepts as the letters h, R and N.
Level: reference · one construct, eight engines
What it means¶
| Shorthand | Expands to | ASCII by default in | Unicode by default in |
|---|---|---|---|
\d |
decimal digits | JavaScript, Ruby, Java, Go, PCRE2 | Python str, Perl, Rust regex |
\w |
letters, digits, _ (and marks, in some) |
JavaScript, Ruby, Java, Go, PCRE2 | Python str, Perl, Rust regex |
\s |
whitespace | Ruby, Java, Go, PCRE2 | Python str, Perl, Rust regex, JavaScript |
\h |
horizontal whitespace (space, tab, NBSP, …) | — | Perl, Ruby, Java, PCRE2 only |
\v |
vertical whitespace (\n, \r, \f, …) |
— | Perl, Java, PCRE2 only — a vertical tab character in Python, JavaScript, Ruby |
\R |
any line break: \n, \r, \r\n, … as one unit |
— | Perl, Ruby, Java, PCRE2 only |
\N |
any character except newline, regardless of (?s) |
— | Perl, PCRE2 only |
\D, \W, \S, \H, \V are the complements, wherever the positive form exists.
Measured¶
Verified output of kw_shorthand_classes_sh.sh — regenerated by tools/run_examples.py, never hand-typed.
construct python perl node ruby java go rust fancy
\d on Arabic-Indic digits \u{660}\u{661} \u{660}\u{661} no no no no \u{660}\u{661} \u{660}\u{661}
\w on Latin-1 \u{E9}t\u{E9} \u{E9}t\u{E9} t t t t \u{E9}t\u{E9} \u{E9}t\u{E9}
\w on Greek \u{3B1}\u{3B2} \u{3B1}\u{3B2} no no no no \u{3B1}\u{3B2} \u{3B1}\u{3B2}
\s on no-break space \u{A0} \u{A0} \u{A0} no no no \u{A0} \u{A0}
\h horizontal space - a\tb no no a\tb - - no
\v vertical space no a\nb no no a\nb no no no
\R any newline - a\r\nb no a\r\nb a\r\nb - - -
\N not a newline - axb no no - - - -
\D \W \S negations a b a b a b a b a b a b a b a b
Reading the table¶
- Row 1,
\don U+0660 U+0661. Python, Perl and Rust match the Arabic-Indic digits; JavaScript, Ruby, Java and Go do not. An input field validated with\d+in the first group accepts a "number" thatInteger.parseIntin the second group would reject — and thatint()in Python happily parses, which the lesson measures the other way round. - Rows 2–3,
\w. The same split. Note the shape of the ASCII answer onété:t— the match starts at the first ASCII letter and stops at the next accent, so a\w+"word" extractor returns fragments rather than nothing, which is harder to notice. - Row 4,
\son a no-break space. JavaScript moves columns: its\shas always been Unicode-aware (the ECMAScript definition includes everyWhite_Spacecharacter) while its\wis ASCII. Ruby, Java and Go say no. - Row 5,
\h. Perl and Java match the tab. Python, Go and Rust'sregexrefuse the escape; JavaScript, Ruby andfancy-regexsayno— for JavaScript that is\hbeing the letterh, for Ruby it is a genuine miss on\t, because Onigmo's\his a hex digit, not horizontal space. Same escape, three meanings and one refusal. - Row 6,
\v. Perl and Java match the\nas vertical whitespace. Python, JavaScript, Ruby, Go and both Rust crates compiled the pattern and matched nothing: their\vis the single character U+000B, vertical tab. A pattern that used\vto mean "any line break" ports from Perl to Python and quietly matches only vertical tabs. - Row 7,
\R. Perl, Ruby and Java match\r\nas one unit — the point of\Ris that it never splits a CRLF. Python, Go and both Rust crates refuse. JavaScript reads\Ras the letter R and finds none. Row 8,\N: Perl alone; Java refuses it.
The trap¶
Not \d being ASCII — that one is at least documented. The trap is the row of no cells that are not refusals: \v in Python, \h in Ruby, and every \h, \v, \R, \N in JavaScript compile fine and mean something else. A refused escape is a bug you find at the first test; a redefined one is a bug you find in production.
Where it is measured in depth¶
- What
\wand\bmatch once the subject is not ASCII — the switch per engine (re.ASCII,(?U),(*UCP),(?-u:…)), and what the ASCII/Unicode split does to\b. - Flags, and where you can turn one on — CRLF handling, where
\Rearns its keep.
See also¶
- Character class · POSIX classes ·
\p{…}— the explicit alternatives. \b— defined in terms of\w.- Unicode text · Multiline text and logs.