\h is a hex digit in Ruby and a blank in Perl¶
Level: 201 · anyone moving a regex between languages
One line: Onigmo reads \h as a hexadecimal digit, Perl reads it as horizontal whitespace, and Python rejects it — so one pattern matches letters in one language, blanks in the next, and raises in the third; [[:xdigit:]] and [[:blank:]] mean the same in Ruby and Perl.
Verified output of h_is_a_hex_digit_rb.rb — regenerated by tools/run_examples.py, never hand-typed.
line = "color: cafe42\tbg: 00ff00"
line.scan(/\h+/) ["c", "cafe42", "b", "00ff00"]
line.scan(/[[:xdigit:]]+/) ["c", "cafe42", "b", "00ff00"]
line.scan(/[[:blank:]]/) [" ", "\t", " "]
line.scan(/\H+/).first(2) ["olor: ", "\t"]
\h+ found cafe42 and 00ff00, and also the c of color and the b of bg: hex digits include six letters. [[:xdigit:]] is the same class, \H its complement, and [[:blank:]] — a space or a tab — is what Perl means by \h.
The same line in Perl¶
Verified output of h_is_a_hex_digit_pl.pl — regenerated by tools/run_examples.py, never hand-typed.
$line =~ /\h+/g [U+0020] [U+0009] [U+0020]
$line =~ /[[:xdigit:]]+/g c cafe42 b 00ff00
$line =~ /[[:blank:]]/g U+0020 U+0009 U+0020
\h+ matched the three blanks: space, tab, space. [[:xdigit:]] and [[:blank:]] agree with Ruby's.
The same line in Python¶
Verified output of h_is_a_hex_digit_py.py — regenerated by tools/run_examples.py, never hand-typed.
re.findall('\\h+', line) re.error: bad escape \h at position 0
re.findall('[0-9A-Fa-f]+', line) ['c', 'cafe42', 'b', '00ff00']
Python's re has no \h and says so, which is the most useful of the three behaviours.
What to do¶
Write [[:xdigit:]] or [0-9a-fA-F] for a hex digit, and [[:blank:]] or [ \t] for a blank, in any pattern that might be copied into another language. In Ruby-only code, \h is fine; it is the port that breaks.