Keeping it simple - tail
We should not need a regular expression, or more than one process, just to count characters.
tail, often used to show the last lines of a file, has an option
--bytes), which seems to be just the right tool for this:
$ printf 123456789 | tail -c 3
(When you are in a shell, it makes sense to use a method like in the answer of mikeserv, because it saves starting the process for
Real Unicode characters?
Now, you ask for the last three characters; That's not what this answer gives you: it outputs the last three bytes!
As long as each character is one byte,
tail -c just works. So it can be used if the character set is
ISO 8859-1 or a variant.
If you have Unicode input, like in the common
UTF-8 format, the result is wrong:
$ printf 123αβγ | tail -c 3
In this example, using
UTF-8, the greek characters alpha, beta and gamma are two bytes long:
$ printf 123αβγ | wc -c
-m can at least count the real unicode characters:
printf 123αβγ | wc -m
Ok, so the last 6 bytes will give us the last 3 characters:
$ printf 123αβγ | tail -c 6
tail does not support handling general characters, and it does not even try (see below): It handles variable size lines, but no variable size characters.
Let's put it this way:
tail is just right for the structure of the problem to solve, but wrong for the kind of data.
Looking further, it turns out that thee GNU coreutils, the collection of basic tools like
cut, is not yet fully internationalized. Which is mainly about supporting Unicode.
cut would be a good candidate to use instead of tail here for character support; It does have options for working on bytes or chars,
--chars is, as of version
cut (GNU coreutils) 8.21, 2013,
Select for printing only the characters in positions listed in CHARACTER-LIST.
The same as `-b' for now, but internationalization will change that.
See also this answer to Can not use `cut -c` (`--characters`) with UTF-8?.