Skip to content

08 — Resources

The primary sources

Everything in this library can be checked against these. Where a page says why, or since which version, it links one of them rather than paraphrasing it.

Ruby

Perl and Python

Unicode, and the one security page

Books

On the shelf beside this library, and worth the time:

  • Text Processing with Ruby — Rob Miller (Pragmatic Bookshelf, 2015). Reading, parsing, transforming and writing text, at book length.
  • Perl One-Liners: 130 Programs That Get Things Done — Peteris Krumins (No Starch Press, 2013). Most of them run under ruby -n or ruby -p after the small changes in the one-liner lesson.
  • Programming Ruby 1.9 & 2.0 — Dave Thomas, with Chad Fowler and Andy Hunt (Pragmatic Bookshelf, 2013). The "Pickaxe", written while the encoding model of chapter 01 was still new.
  • The Ruby Programming Language — David Flanagan and Yukihiro Matsumoto (O'Reilly, 2008). Co-written by Ruby's author, as Ruby 1.9 arrived.

The same idea in the sibling libraries

Each row is a lesson here and its counterparts elsewhere. The Perl and Python comparisons are also inside the lessons themselves, as runnable programs.

This library Perl Encodings Python Java text Rust C
A string is bytes plus a label Decode at the edges ↗ Encode and decode are verbs ↗ Encode and decode ↗ Encodings ↗ Strings ↗
Mixing encodings raises "Wide character in print" ↗ Mojibake ↗ The default charset ↗
Invalid bytes get in, and fail later Decode at the edges ↗ Validation is a boundary ↗ Malformed input ↗
String.new is binary Text and binary are both bytes ↗
File.read depends on the locale Opening a file ↗ The default charset ↗
The BOM is kept A BOM in a CSV ↗ The BOM is not stripped ↗
chomp knows about CRLF chomp leaves the CR ↗ CRLF vs LF ↗ What ends a line ↗ RFC 1212 ↗
length counts code points length counts code points ↗ A code point is not a character ↗ Counting characters ↗ Length is three numbers ↗ Four lengths ↗
Normalization is built in Preparing a string ↗ Normalization ↗ Normalization and equality ↗
Case mapping is full Unicode fc is how to compare without case ↗ Case is not per character ↗ Lowercasing is not folding ↗ Case is locale-sensitive ↗ Wrong, but not unsafe ↗
\w is ASCII The Unicode bug ↗ What a regex matches ↗ \w is ASCII by default ↗
Backtracking has a cache PCRE2 ↗
String literals are chilled &'static str
One-liner switches came from Perl -n and -p are a loop ↗ awk is three programs ↗ -c is not the prompt ↗
split has an awk mode split has sharp edges ↗ split has sharp edges ↗ Splitting on nothing ↗
pack speaks Perl Packing a record ↗ Byte order on the wire ↗
to_i never fails Numbers from text ↗ Parsing a number from text ↗
Padding counts code points The format mini-language ↗ The format mini-language ↗

The contrast is the point of having all of them. Ruby labels each string with an encoding; Perl keeps one flag, bytes or characters; Python keeps text and bytes in two types; Java and Rust fix one encoding inside every string — UTF-16 and UTF-8. Each choice buys something and costs something, and the rows above are where the costs show.

Tools worth having

  • ruby -W:deprecated — every deprecation warning, including mutation of a chilled literal.
  • Regexp.linear_time? — in a test, next to every pattern that faces user input.
  • xxd or od -c — the only reliable way to see a BOM, a stray \r or an invalid byte for what it is.
  • perl -CSD — Perl with UTF-8 layers on standard streams and on files it opens, for comparing against Ruby without writing binmode.