9

I have a string in a shell/bash script. I want to print the string with all its "special characters" (eg. newlines, tabs, etc.) printed as literal escape sequences (eg. a newline is printed as \n, a tab is printed as \t, and so on).

(Not sure if I'm using the correct terminology; the example should hopefully clarify things.)

Example

The desired output of...

a="foo\t\tbar"
b="foo      bar"

print_escape_seq "$a"
print_escape_seq "$b"

...is:

foo\t\tbar
foo\t\tbar
  1. $a and $b are strings that were read in from a text file.
  2. There are two tab characters between foo and bar in the $b variable.

An attempt

This is what I've tried:

#!/bin/sh

print_escape_seq() {
  str=$(printf "%q\n" $1)
  str=${str/\/\//\/}
  echo $str
}

a="foo\t\tbar"
b="foo      bar"

print_escape_seq "$a"
print_escape_seq "$b"

The output is:

foo\t\tbar
foo bar

So, it doesn't work for $b.

Is there an entirely straightforward way to accomplish this that I've missed completely?

asymptote
  • 305
  • 4
  • 12
  • are you looking to visualize the `\t` and `\n` chars, or would you take this output and then use it, expecting that `\t,\n` (etc), would work as usual? Good luck. – shellter Jan 18 '15 at 18:02
  • Yes, to visualise the `\t` and `\n` characters. The output is just for display on `stdout`. – asymptote Jan 18 '15 at 18:07
  • 1
    A good answer below, but maybe you should get comfortable reading the output of the shell debug/trace feature `set -vx; cmd1; cmd2 ... ; set +vx`. It will visualize your strings "for free". ;-) Good luck. – shellter Jan 18 '15 at 19:10

2 Answers2

3

You will need to create a search and replace pattern for each binary value you wish to replace. Something like this:

#!/bin/bash

esc() {
    # space char after //
    v=${1// /\\s}   
    # tab character after //
    v=${v// /\\t}
    echo $v
}
esc "hello world"
esc "hello  world"

This outputs

hello\sworld
hello\tworld
user590028
  • 10,743
  • 3
  • 34
  • 55
2

Bash has a string quoting operation ${var@Q}

Here is some example code


bash_encode () {
  esc=${1@Q}
  echo "${esc:2:-1}" 
}

testval=$(printf "hello\t\tworld")
set | grep "^testval="
echo "The encoded value of testval is" $(bash_encode "$testval")

Here is the output

testval=$'hello\t\tworld'
The encoded value of testval is hello\t\tworld
Frobbit
  • 1,570
  • 14
  • 28