How can the white space character be escaped in printf for the purpose of this script that currently runs in a Cygwin client? The line containing the whitespace (which by itself works from the command line as echo $SPC) is

SPC=$(printf \\$(printf '%03o' 32))

In case you might wonder why, in this code I am trying to simulate an associative array such that it is not dependent on Bash 4+...would like this to be a generic example that theoretically can be run in virtually any bash environment.

Here is the entire script:


SPC=$(printf \\$(printf '%03o' 32))

OUTLOOKS=( "Cancel^Do$SPCnot$SPCtry$SPCto$SPCsend$SPCmessage$SPCvia$SPCOutlook"
           "Outlook$SPC2010^C:\Program$SPCFiles\Microsoft$SPCOffice\Office14" )

printOutlooksArraySelectionList() {
    printf "\t\t\E[37;1;44m%-0s %s %s %s\033[0m" $LIST_TITLE
    DEFAULT_VALUE="Outlook 2010"
    for i in "${OUTLOOKS[@]}"; do
        if [ "$key" == "$DEFAULT_KEY" ]; then
            printf "\t\E[37;44m%-3s %-13s\033[0m \E[1;34;40m%-41s\033[0m\n" \
                   $index $key $value
    ((LAST_INDEX = index - 1))


Would like the output to look like the following:


    0   Cancel        Do not try to send message via Outlook

    1   URL           Just the mailto URL

    2   Outlook 2003  C:\Program Files\Microsoft Office\Office12

    3   Outlook 2007  C:\Program Files\Microsoft Office\Office12

    4   Outlook 2010  C:\Program Files\Microsoft Office\Office14

To work-around, I ended up not using printf, but instead:

echo -e "\t\E[37;44m${index}\t${key}\033[0m\t\t\E[1;34;40m${value}\033[0m"

adequate for my purposes with this script.

  • Since you've already used quotes around the strings, using $SPC in them is not necessary and gives you no benefit. You don't need any definition of space there.

  • As Gilles pointed out, strings like "URL^Just$SPCthe$SPCmailto$SPCURL" contain non-existing variables. A variable ends either at a character that cannot be used in any variable name, or when it is (properly) delimiterred with {} as in ${key}.

  • Thank you, rozcietrzewiacz; your suggestion to put the SPC variable into ${SPC} solved the problem. – mikequentel Nov 18 '11 at 12:46
  • Thanks for accepting, but you really should just get rid of the $SPC variable instead. It is useless - just put spaces in there. – rozcietrzewiacz Nov 18 '11 at 13:03
  • When I just put spaces in the text, the script does not behave as expected in Cygwin. The script works without the SPC variable (as you suggest getting rid of $SPC) in a true Linux environment like Ubuntu 11.04 (just tested it in that environment). However, have not gotten it to work in Cygwin on Windows XP. – mikequentel Nov 18 '11 at 15:46
  • This sounds very strange - you might want to investigate this further (use a simplest script possible). There might be some other error that causes this. – rozcietrzewiacz Nov 18 '11 at 15:50
  • After further investigation, I think there is indeed something else that was causing the error in Cygwin. I again tested using just " " (no SPC variable) in the script, in Cygwin, and now it works. Could be something about my workstation configuration or some other factor. Weird. Again, thank you for pointing out the variable expansion aspect, in general. – mikequentel Nov 18 '11 at 16:18

I don't understand what you're trying to do. Your code does set SPC to a string of length 1 whose single character is a space. This is a highly convoluted way of doing it: SPC=" " would work just as well and be comprehensible.

I haven't reviewed your whole script, but I do see something wrong later down: you write things like "URL^Just$SPCthe$SPCmailto$SPCURL". This produces the string URL^Just, because the variables $SPCthe, $SPCmailto and $SPCURL are not defined. When a variable expansion is immediately followed by a character that could be part of the variable name, you need to indicate the end of the variable name, for example by putting the name into braces: URL^Just${SPC}the${SPC}mailto${SPC}URL. I don't understand why you're not writing "URL^Just the mailto URL", though.

For your encoding of small hash tables, I suggest using two array, once for keys and one for values. That way, you can store arbitrary strings, without fearing encoding issues. Here's a sketch of what lookup and addition can look like (taking the names of the keys and values arrays as parameters is left as an exercise):

lookup () { # $1=key; set value to the value found
  for ((i=1; i<=${#keys}; i++)); do
    if [[ ${keys[$i]} = $1 ]]; then value=${values[$i]}; return 0; fi
  unset value; return 1
add () { # $1=key $2=value
  for ((i=1; i<=${#keys}; i++)); do
    if [[ ${keys[$i]} = $1 ]]; then values[$i]=$2; return; fi
  keys[$i]=$1; values[$i]=$2

A more efficient method would be to store each entry in a shell variable. For example, if the table foo maps somekey to somevalue, then set the variable table_foo_somekey=somevalue. You need to encode the keys into alphanumerics, which is non-trivial (one method is to hash the keys, e.g. with sha1, and store the key in table_foo_${sha1_of_somekey}_key and the value in table_foo_${sha1_of_somekey}_key). If you need to enumerate the keys in a table, you need to store the list separately.

Or, when you need things that go beyond the capabilities of a simple shell, you could reach for a more powerful tool. Ksh93 (not pdksh), bash 4 and zsh all have associative arrays. Beyond that, there's Perl and Python and the rest of them.

  • Thank you for the comments, suggestions, and information...I changed the assignment: SPC=" " but the result is still not as expected. Initially, I tried the '"URL^Just the mailto URL"' syntax, but it does not work as expected in Cygwin, hence the attempts at using escape characters that represent the whitespace character. – mikequentel Nov 18 '11 at 4:55
  • 1
    But what are you expecting from SPC? – ДМИТРИЙ МАЛИКОВ Nov 18 '11 at 6:52
  • 1
    @MikeQuentel I guarantee you that your SPC variable will not help with whatever problem you're having. The space character is not different on Cygwin. Remove it, which will fix some of the problems with your script as I've explained. Then, if you still need help, post your updated, simplified script, and explain what the script does, what you expect from the script, and how they differ. – Gilles Nov 18 '11 at 8:11

I've already mentioned some misunderstanding of that problem. But anyway.

The line containing the whitespace (which by itself works from the command line as echo $SPC) is

SPC=$(printf \\$(printf '%03o' 32))

Actually, that line do not containing any whitespaces. It expands in

printf \\040

which expands in nothing good. And printfing a printf output is a really bad idea at all.

Print could show space symbols if you want it:

$> printf '  %03o\n' 32

Leading nulls and leading zeros too:

$> printf "%010o\n" 32

$> printf "% 10o\n" 32

UPD by comment:

$> printf '\\%03o\n' 32
  • Thank you for the clarification. Similarly, I had previously tried using the value of printf "\040" (octal value) which works at the command line by itself, but using the octal does not work with the script. – mikequentel Nov 17 '11 at 21:53
  • The line SPC=$(printf \\$(printf '%03o' 32)) does set SPC to a single space character, in a highly convoluted way. While I agree with your “bad idea” characterisation, this bit does work as (possibly) intended. – Gilles Nov 18 '11 at 10:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.