. — any character, except the ones it is not¶
One line: . matches one character that is not a newline — where "newline" is \n alone in Python, Perl, Ruby, Go and Rust, and also \r in JavaScript and Java; the flag that makes it match newlines is s in six engines and m in Ruby; and whether an emoji is one character or two depends on JavaScript's u flag.
Level: reference · one construct, eight engines
What it means¶
Three questions hide inside "any character", and engines answer each one differently:
- Which line terminators does it refuse?
\neverywhere.\rtoo in JavaScript and Java, whose definition of a line break is CRLF-aware. Soa.bmatchesa\rbin six engines and not in those two. - What flag lets it match them?
(?s)/re.S/DOTALL/ thesflag — except in Ruby, where the letter ism, and(?s)is a compile error. - What is one character? A code point, in every engine that operates on decoded text — except JavaScript without the
uflag, which operates on UTF-16 code units and sees an emoji as two of them.
Measured¶
Verified output of kw_dot_sh.sh — regenerated by tools/run_examples.py, never hand-typed.
construct python perl node ruby java go rust fancy
ordinary axb axb axb axb axb axb axb axb
across \n no no no no no no no no
across \n with (?s) a\nb a\nb - - a\nb a\nb a\nb a\nb
across \n, node s flag no no a\nb no no no no no
across \n with (?m) no no - a\nb no no no no
across \r a\rb a\rb no a\rb no a\rb a\rb a\rb
one astral character \u{1F600} \u{1F600} no \u{1F600} \u{1F600} \u{1F600} \u{1F600} \u{1F600}
astral, node u flag \u{1F600} \u{1F600} \u{1F600} \u{1F600} \u{1F600} \u{1F600} \u{1F600} \u{1F600}
escaped dot no no no no no no no no
dot inside a class no no no no no no no no
Reading the table¶
- Row 2 is unanimous: no engine's plain
.crosses\n. - Row 3,
(?s). Six engines cross it. JavaScript is-(no inline flags — row 4 passessas an argument and it works). Ruby is-:(?s)does not exist there. Row 5 is Ruby's spelling —(?m)— and it is the only engine where(?m)changes what.does. In the other six,(?m)is about^and$, and.still stops at the newline. - Row 6,
a\rb. Python, Perl, Ruby, Go and Rust match across a carriage return; JavaScript and Java refuse. A pattern tested on Unix line endings and shipped against CRLF files behaves differently in exactly those two engines — which happen to be the two most likely to be running on the same Windows machine that produced the file. - Rows 7–8, one astral character. Seven engines see U+1F600 as one character and match
^.$. JavaScript withoutusees two code units and fails; withuit agrees. This is the same fault line as\p{…}needingu— JavaScript has two string models and the flag picks one. - Rows 9–10. Escaped, or inside a class,
.is a full stop. Bothnocells are correct:axbcontains no full stop.
The trap¶
.* as "everything". It is everything on one line, and on Windows input in JavaScript or Java it is everything up to the \r. The fix is not to add \r to a class — it is to decide whether you meant a line or the whole text, and say so with (?s) (or Ruby's (?m)), or to use [\s\S] in JavaScript when the flag cannot be reached.
Where it is measured in depth¶
- Flags, and where you can turn one on — the
s/mletter collision and the CRLF rows across every engine. - What
\wand\bmatch — the code-unit versus code-point question for the other shorthands.
See also¶
- Character class · Shorthand classes — the alternatives to "anything".
- Grapheme cluster
\X— "one character" as a person counts it, which.is not. - Inline flags · Multiline text and logs.