tr: Bad String
Trying to mangle some characters resulted in a weird error message:
$ echo hello | tr [:lower:] [:upper:] Bad stringHuh? Before debugging any further, searching the interwebs returns quite a few results, of course, so let's look at our options then:
$ type tr tr is /usr/bin/tr $ find /usr -type f -perm -0500 -name tr -ls 2>/dev/null 32054 11 -rwxr-xr-x 1 root bin 9916 Jan 23 2005 /usr/ucb/tr 16674 19 -r-xr-xr-x 1 root bin 18540 Jan 23 2005 /usr/xpg6/bin/tr 410 20 -r-xr-xr-x 1 root bin 19400 Jan 23 2005 /usr/bin/tr 75251 19 -r-xr-xr-x 1 root bin 18520 Jan 23 2005 /usr/xpg4/bin/trBesides our default from
SUNWcsu
, we have three other versions of tr(1) available.
The UCB version tries do do...something:
$ echo hello | /usr/ucb/tr [:lower:] [:upper:] heuupApparently it replaces each character (position) literally, but fails to recognize the bracket expressions. Since the UCB tools were removed in later versions anyway, let's skip that for now. The two X/Open versions seem to manage:
$ echo hello | /usr/xpg6/bin/tr [:lower:] [:upper:] HELLO $ echo hello | /usr/xpg4/bin/tr [:lower:] [:upper:] HELLOBut why wouldn't it work with the
SUNWcsu
version? truss(1) reports a missing file, but this turns out to be a red herring:
$ echo hello | truss -elfda tr [[:lower:]] [[:upper:]] Base time stamp: 1481011767.7308 [ Tue Dec 6 09:09:27 MET 2016 ] 26125/1: 0.0000 execve("/usr/bin/tr", 0xFFBFFC9C, 0xFFBFFCAC) argc = 3 26125/1: argv: tr [[:lower:]] [[:upper:]] 26125/1: envp: LC_MONETARY=en_GB.ISO8859-15 TERM=xterm SHELL=/bin/bash 26125/1: LC_NUMERIC=en_GB.ISO8859-15 LC_ALL=en_US.UTF-8 26125/1: LC_MESSAGES=C LC_COLLATE=en_GB.ISO8859-15 LANG=en_US.UTF-8 26125/1: LC_CTYPE=en_GB.ISO8859-1 LC_TIME=en_GB.ISO8859-15 [...] 26125/1: 0.0061 stat64("/usr/lib/locale/en_US.UTF-8/libc.so.1", 0xFFBFE8D0) Err#2 ENOENT 26125/1: 0.0063 open("/usr/lib/locale/en_US.UTF-8/LC_MESSAGES/SUNW_OST_OSCMD.mo", O_RDONLY) Err#2 ENOENT 26125/1: 0.0064 fstat64(2, 0xFFBFEA38) = 0 Bad string 26125/1: 0.0064 write(2, " B a d s t r i n g\n", 11) = 11 26125/1: 0.0065 _exit(1)(Un)fortunately I had my share of weird experiences with character encodings and the like. And indeed, if we use a single-byte locale,
/usr/bin/tr
works just fine:
$ echo $LC_ALL en_US.UTF-8 $ echo hello | LC_ALL=en_US tr [[:lower:]] [[:upper:]] HELLOAnother workaround would be to use another expression, if possible:
$ echo hello | tr [a-z] [A-Z] HELLOIn newer SunOS versions,
/usr/bin/tr
has been fixed and works as expected.