When I try to separate a string into its characters, it fails on spaces and newlines:
str=" random string
"
echo ${str//?/ \'&}
' 'r 'a 'n 'd 'o 'm ' 's 't 'r 'i 'n 'g '
The parameter substitution somehow ignores the spaces and newlines and interprets them as empty, is there a way to make it recognize them?
That's post-expansion word-splitting. If you quote the parameter expansion, you'll see all leading, interword, and trailing whitespace preserved.
$ str=" random string
"
$ echo ${str//?/ \'&}
' 'r 'a 'n 'd 'o 'm ' 's 't 'r 'i 'n 'g '
$ echo "${str//?/ \'&}"
' 'r 'a 'n 'd 'o 'm ' 's 't 'r 'i 'n 'g '
$
Technically, none of the spaces introduced by the substitution operator survive the unquoted parameter expansion; they simply become part of the whitespace used to separate arguments to echo
, and echo
re-inserts a single space between each of the arguments it writes to standard output. Compare:
$ echo ${str//?/ \'&}
' 'r 'a 'n 'd 'o 'm ' 's 't 'r 'i 'n 'g '
$ echo "${str//?/ \'&}"
' 'r 'a 'n 'd 'o 'm ' 's 't 'r 'i 'n 'g '
If, based on one of your short-lived comments, you are trying to dynamically construct the equivalent of the command
set -- ' ' 'r' 'a' 'n' 'd' 'o' 'm' ' ' 's' 't' 'r' 'i' 'n' 'g' '
'
I suggest simply iterating over the string and executing multiple set
commands to build up the arguments.
set --
for ((i=0; i < ${#str}; i++)); do
set -- "$@" "${str:i:1}"
done