Without the aid of the escape mechanism, how to put a raw string into a variable?

Hi guys and gals...
I have been racking my brains with this one and I can't find anything about it...
Consider the code and the results below:

#!/usr/local/bin/dash

# #!/bin/sh
# #!/bin/bash
# rawstring.sh

: > /tmp/rawstring

# ############# THIS WORKS ADMIRABLY! ##############
NUM=32
STRING=""

while [ ${NUM} -le 126 ]
do
    printf \\$( printf "%03o" "${NUM}" ) >> /tmp/rawstring
    NUM=$(( NUM + 1 ))
done

STRING=$( cat /tmp/rawstring )
echo ""
/bin/echo "${STRING}"
echo ""
echo "${STRING}"
# ########## END OF THIS WORKS ADMIRABLY! ##########

# ##################################################
# THIS HOWEVER FAILS CATASTROPHICALLY!
echo ""
echo "This is where the error is with or without leading and trailing"
echo "single or double quotes:-"
echo ""

STRING=' !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'

# The line below does not even get executed!
echo "${STRING}"
# ##################################################

Results on OSX 10.14.x:

Last login: Sun Apr 12 09:52:48 on ttys000
AMIGA:amiga~> cd Desktop/Code/Shell
AMIGA:amiga~/Desktop/Code/Shell> ./rawstring.sh

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

This is where the error is with or without leading and trailing
single or double quotes:-

./rawstring.sh: 33: ./rawstring.sh: Syntax error: "(" unexpected
 AMIGA:amiga~/Desktop/Code/Shell> _

As you can see saving a rawstring to disk and retrieving it again works but trying to force a rawstring without the escape mechanism fails catastrophically.
This is one of the USEFUL uses of 'cat' as it works admirably in this case but it requires I/O to do so...
I need to avoid the use of the escape mechanism inside the failing condition in case I want to __edit__ said rawstring inside any code.

I would like to know what is different about putting a rawstring into a variable using 'cat' and attempting to do so using hard coding.

Bazza...

Your STRING assignment ends with the second single quote after the & :

STRING=' !"#$%&'

and thus the following ( is not recognized by the shell:

Of course not - it is part of the single quoted literal string started with the very last character two lines above.

I'm afraid you won't escape escaping in some way. Try e.g. using this mechanism man bash :

STRING=$' !"#$%&\47()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'
2 Likes

Hi RudiC...

I already know about conjoining strings and this is the way 'set' does it from the working part of the code:

STRING=' !"#$%&'"'"'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'

But I did say I would like to be able to edit the STRING on the fly so what if I deleted say ' or " inside the STRING?

EDIT:
Just seen your edit and that looks like a good idea thanks I'll try it...

An embedded string in a shell script is normally fenced with either ' or " so you need to escape these characters inside the string.
Try a here doc:

read STRING <<"EOT"
 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
EOT

Now the fence is a custom word.
You must quote it to prevent variable substitutions.
BTW if a file or a here doc has got one line then read is smarter than cat.

Last login: Sun Apr 12 14:58:50 on ttys000
AMIGA:amiga~> read STRING <<"EOT"
>  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
> EOT
AMIGA:amiga~> 
AMIGA:amiga~> echo "${STRING}"
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~
AMIGA:amiga~> 
AMIGA:amiga~> # The space is missing!
AMIGA:amiga~> 
AMIGA:amiga~> # Also the '\' too.
AMIGA:amiga~> 
AMIGA:amiga~> echo "${#STRING}"
93
AMIGA:amiga~> # Should be 95.
AMIGA:amiga~> 
AMIGA:amiga~> read -r STRING <<"EOT"
>  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
> EOT
AMIGA:amiga~> echo "${STRING}"
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
AMIGA:amiga~> 
AMIGA:amiga~> # The space is still missing.
AMIGA:amiga~> 
AMIGA:amiga~> echo "${#STRING}"
94
AMIGA:amiga~> _

cat does not omit the space, (decimal character 32).

--- Post updated at 05:11 PM ---

Hi Rudic...

(HOPEFULLY THIS DOES NOT ATTACH TO THE PREVIOUS, if it does apologies...)

Last login: Sun Apr 12 15:58:43 on ttys000
AMIGA:amiga~> cd Desktop/Code/Shell
AMIGA:amiga~/Desktop/Code/Shell> ./rawstr.sh

Raw string:-
 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
Number of characters:-
98

Raw string:-
 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
Number of characters:-
95

Look at the real string inside the environment:-

Apple_PubSub_Socket_Render='/private/tmp/com.apple.launchd.glJfvo3uxT/Render'
HOME='/Users/amiga'
IFS='     
'
LANG='en_GB.UTF-8'
LINENO=''
LOGNAME='amiga'
OLDPWD='/Users/amiga'
OPTIND='1'
PATH='/Library/Frameworks/Python.framework/Versions/3.8/bin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/Users/amiga/Programs:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin'
PPID='4629'
PS1='AMIGA:\u\w> '
PS2='> '
PS4='+ '
PWD='/Users/amiga/Desktop/Code/Shell'
SHELL='/bin/bash'
SHLVL='1'
SSH_AUTH_SOCK='/private/tmp/com.apple.launchd.gtetHEIugk/Listeners'
STRING=' !"#$%&'"'"'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'
TERM='xterm-256color'
TERM_PROGRAM='Apple_Terminal'
TERM_PROGRAM_VERSION='421.2'
TERM_SESSION_ID='8D9826C6-8625-4C9F-A6C9-E7CBDDEAC0CE'
TMPDIR='/var/folders/9c/bb_c667j5nj5cbbkw__1l8n40000gp/T/'
USER='amiga'
XPC_FLAGS='0x0'
XPC_SERVICE_NAME='0'
_='./rawstr.sh'
AMIGA:amiga~/Desktop/Code/Shell> _

Thanked your previous post...

#!/usr/local/bin/dash
# rawstr.sh

STRING=' !"#$%&\047()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'

# Assumption that this is using dash's builtin 'echo'...
echo ""
echo "Raw string:-"
echo "${STRING}"
echo "Number of characters:-"
echo "${#STRING}"

STRING=$( echo "${STRING}" )

echo ""
echo "Raw string:-"
echo "${STRING}"
echo "Number of characters:-"
echo "${#STRING}"
echo ""
echo "Look at the real string inside the environment:-"
echo ""

set

# YES! (Fist in the air!)
# Nice one RudiC, I now have an idea for a convoluted means
# editing a raw ASCII string variable in POSIX mode and will
# upload IF it works at a later date...

OSX 10.14.x, default bash terminal, calling dash inside the code...

I forgot that read by default omits leading space (add IFS=), and mistreats a backslash (add -r).
Should be

IFS= read -r STRING << "EOT"
...
2 Likes