I am just trying to convert an array into string, while preserving the white spaces. This is what I have:

readarray -t arr < <(grep -o . <<< "$INPUT")

echo "${arr[*]}"

I tried it with ${parameter//pat/string}, setting IFS to IFS=' ' and its obviously wrong. I am unable to produce the desired output.

printf %q "$IFS" outputs $' \t\n'

I run my script with command ./rev_arr "I'm Hungry!"


Expected Output: enter image description here


2 Answers 2


Although I don't quite see the usefulness of reading a string as separate characters into an array, just to re-form the string again, setting IFS to a single space will insert a single space between the elements of the array when using "${arr[*]}". Instead, set IFS to an empty string:

readarray -t arr < <( grep -o . <<<"$1" )
( IFS=''; printf '%s\n' "${arr[*]}" )

I'm using a subshell for the assignment to IFS and for the printf as to not change the value of IFS for the rest of the script.

  • There is no need to change IFS, a printf '%s' "${arr[@]}"; echo works perfectly well.
    – user232326
    Dec 7, 2018 at 14:39

The use of a * in "${arr[*]}" is introducing the first character from IFS as separator for each element of the array. You could try a change of IFS:

 readarray -t arr < <(grep -o . <<< "$input")
 ( IFS=''; echo "${arr[*]}" )

Or try a complex evaluation delay with eval:

 readarray -t arr < <(grep -o . <<< "$input")
 IFS='' eval 'echo "array= ${arr[*]}"'

But there is no real need to start a subshell (to avoid changing the IFS in the present shell) or a risk increasing eval when a simple printf is all you need:

 readarray -t arr < <(grep -o . <<< "$input")
 printf '%s' "${arr[@]}" $'\n'

Note that the use of grep will remove any internal newlines from $input.

To be able to get the newlines in the array elements (for small inputs):

 [[ $input =~ ${input//?/(.)} ]] && arr=("${BASH_REMATCH[@]:1}")
 printf '%s' array= "${arr[@]}" $'\n'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .