Bash: Populating Array with Elements Containing Spaces and Special Characters

I want to be able to populate elements of an an array with arbitrary strings, i.e. strings that may contain \ and spaces for instance. I wrote this :

#!/bin/bash
function populate_array () {
    if [ "$#" -gt 0 ] ; then
        # Enter array w/ elements as argument of executable 
        array=($@)
        n=$#
    else
        # Invoke executable with no arg,, enter array element later
        read -p "Enter array elements separated by spaces: " -a array  
        n=${#array[@]} 
    fi
    printf "%d array elements \n" "$n"
} 

populate_array "$@"

while (("$n" > 0))   # while [ "$n" -gt 0 ] ALSO WORKS
do
    printf "%s \n" "${array[$n-1]}"
    n=$n-1
done
exit 0

The while block is just meant for the purpose of checking array elements. The function is simple enough to work well for arguments that contain no space or \. Not otherwise.

Trying to enter arguments to the executable as:

#!> bash [scriptname] lkl1239 343.4l 3,344 (34) "lklk  lkl" lkaa\ lkc

I'd like to see 6 arguments:

lkl1239
343.4l 
3,344
(34)
lklk  lkl
lkaa lkc

Instead I get thrown:

  • For ( => bash: syntax error near unexpected token `34'
  • Space containing strings are interpreted as x+1 strings, where x is the number of non consecutive spaces neither at the beginning nor at the end of a string.
  • Bash ignores what comes after the first occurence of \

How is this done ?

4 Answers

What you're doing is tricky. The normal way is to avoid this and just pass the array values as arguments. In order to have both options, you would have to use eval:

#!/bin/bash
function populate_array () {
    if [ "$#" -gt 0 ] ; then
        # Enter array w/ elements as argument of executable 
        # Note the quotes, they are needed
        array=("$@");
        n=$#
    else
        # Invoke executable with no arg, enter array element later
        # Read a string instead of an array and use eval to make it
        # into an array. That way, you can use tricks like escaping
        # spaces. You also need the -r option to protect the backslashes
        # so that eval will see them. 
        read -r  -p "Enter array elements separated by spaces: " string
        eval array="( $(printf '%s\n' "$string") )"
        n=${#array[@]} 
    fi
    printf "%d array elements \n" "$n"
} 

populate_array "$@"

while (("$n" > 0))   # while [ "$n" -gt 0 ] ALSO WORKS
do
    printf "%s \n" "${array[$n-1]}"
    n=$n-1
done
exit 0

You still need to escape the parentheses if you pass the array values as an argument since ( ) are reserved characters for bash. With that caveat, the script above should work as you expect:

$ foo.sh lkl1239 343.4l 3,344 \(34\) "lklk  lkl" lkaa\ lkc
6 array elements 
lkaa lkc 
lklk  lkl 
(34) 
3,344 
343.4l 
lkl1239 

And

$ foo.sh
Enter array elements separated by spaces:  lkl1239 343.4l 3,344 \(34\) "lklk  lkl" lkaa\ lkc 
6 array elements 
lkaa lkc 
lklk  lkl 
(34) 
3,344 
343.4l 
lkl1239 
3

Just quote the $@ as you already correctly do in the function invocation:

array=("$@")

As man bash puts it:

"$@" is equivalent to "$1" "$2" ...

0

Special characters typically have to be escaped with backslash, like so:

 $ array-script.sh   lkl1239 343.4l 3,344 \(34\) "lklk  lkl" lkaa\ lkc                                                                  
6 array elements 
lkaa lkc 
lklk  lkl 
(34) 
3,344 
343.4l 
lkl1239 

The brackets are treated by the shell as metacharacters, hence need to be escaped. The backslash in lkaa\ lkc already escapes the space between lkaa and lkc, so those two strings are treated as one. Same as with cd /home/user/bin/NAME\ WITH\ SPACE

And from man bash:

   metacharacter
                  A character that, when unquoted, separates words.  One of the following:
                  |  & ; ( ) < > space tab
5

can you try by placing below at top of script

SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

and

IFS=$SAVEIFS 

in bottom of script

Your Answer

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

Robert Thorne

Robert Thorne

Automotive & Future Transportation Editor

Robert Thorne covers electric vehicle innovations, autonomous driving systems, global mobility trends, and automotive engineering developments.

Share this article
Twitter Facebook Pinterest