Monday, December 19, 2011

How to make ksh93 echo newlines

The short story

If you can't get echo to interpret escape sequences like \n or \c with ksh and it does something like this.
$ echo "\n"
\n
Try the following.
$ builtin getconf; getconf UNIVERSE - att
$ echo "\n"

If your are under Ubuntu or the above doesn't work just change - for =
$ builtin getconf; getconf UNIVERSE = att
$ echo "\n"
 

For those interested in the details

The other day I had to port an old application with lots of shell scripts from a Solaris machine to RHEL 5. Those scripts use escapes sequences inside echo statements. It was fine on the Solaris machine but on RHEL all the escape sequences were displayed verbatim.
$ echo "\n"
\n
The only difference was that the Solaris server came with ksh88 and RHEL 5 comes with ksh93.

The main problem is that echo is not standardized. Some distributions make it interpret escape sequences by default but other require the -e option. You should avoid using echo if you write a portable script !

My first try was to alias echo to "echo -e" but it does not work inside scripts as aliases can't be passed to subshells like you could do in ksh88 with alias -x.
I then tried to put it into the .profile or .kshrc but unfortunately in ksh93 non-interactive, non-login shells do not read any profile file, ever !

I was stuck when I fell on the UNIVERSE variable (don't think it is documented in the man page). Basically ksh93 behaves in two different ways with respect to echo depending on how it has been compiled.
UNIVERSE can be :
  • ucb (University of California, Berkeley) : echo doesn't interpret escape sequences.
  • att (AT&T): echo interprets escape sequences.

    If you encountered the same problem it surely means that your UNIVERSE variable is set to ucb. There are two ways to check that.
    1. Look at the environment variable _AST_FEATURES
      $ env | grep AST
      _AST_FEATURES=UNIVERSE -ucb
      
    2. Use the built-in version of getconf. (By default my ksh93 uses getconf form the path which doesn't know UNIVERSE)
      $ builtin getconf
      $ getconf UNIVERSE
      ucb
      
    Fixing the problem is then just a simple matter of setting it to att. Again two ways.
    1. Changing the environment variable _AST_FEATURES. The main issue is that on RHEL it does not work immediately , only in subshells.
      $ export _AST_FEATURES="UNIVERSE - att"
      $ echo "\n"
      \n
      $ ksh
      $ echo "\n"
      
      
    2. Changing UNIVERSE via the built-in getconf. And it works immediately.
      $ builtin getconf; getconf UNIVERSE - att
      $ echo "\n"
      
      
      This is what I put into the .profile to get those scripts working.

    For Ubuntu 11 users or if the above did not work you should use = instead of - into the UNIVERSE variable. It looks like there is again a difference amongst the different shipped versions of ksh93 and some do not accept - to set UNIVERSE.
    1. Unlike RHEL changing the environment variable works immediately on Ubuntu.
    2. $ export _AST_FEATURES="UNIVERSE = att"
    3. Or the second version if you prefer.
      $ builtin getconf; getconf UNIVERSE = att
      

    No comments:

    Post a Comment