66

I'm trying to declare an empty array in Shell Script but I'm experiencing an error.

#!/bin/bash

list=$@

newlist=()

for l in $list; do

        newlist+=($l)

done

echo "new"
echo $newlist

When I execute it, I get test.sh: 5: test.sh: Syntax error: "(" unexpected

3
  • Code runs without error Commented Sep 20, 2013 at 16:21
  • 3
    Are you sure you are running your script with bash? It looks like the script is being run using sh, in which case arrays are not supported. Commented Sep 20, 2013 at 16:21
  • 1
    Also, assigning $@ to another parameter loses the benefits of $@, namely that white-space within a single command line argument is preserved. Ditch list and use for l in "$@"; do directly. Commented Sep 20, 2013 at 16:23

6 Answers 6

34

In BASH 4+ you can use the following for declaring an empty Array:

declare -a ARRAY_NAME=()

You can then append new items NEW_ITEM1 & NEW_ITEM2 by:

ARRAY_NAME+=(NEW_ITEM1)
ARRAY_NAME+=(NEW_ITEM2)

Please note that parentheses () is required while adding the new items. This is required so that new items are appended as an Array element. If you did miss the (), NEW_ITEM2 will become a String append to first Array Element ARRAY_NAME[0].

Above example will result into:

echo ${ARRAY_NAME[@]}
NEW_ITEM1 NEW_ITEM2

echo ${ARRAY_NAME[0]}
NEW_ITEM1

echo ${ARRAY_NAME[1]}
NEW_ITEM2

Next, if you performed (note the missing parenthesis):

ARRAY_NAME+=NEW_ITEM3

This will result into:

echo ${ARRAY_NAME[@]}
NEW_ITEM1NEW_ITEM3 NEW_ITEM2

echo ${ARRAY_NAME[0]}
NEW_ITEM1NEW_ITEM3

echo ${ARRAY_NAME[1]}
NEW_ITEM2

Thanks to @LenW for correcting me on append operation.

Sign up to request clarification or add additional context in comments.

1 Comment

I also find that you can append multiple items at once with ARRAY_NAME+=(NEW_ITEM1 NEW_ITEM2). So you're really just concatenating two arrays. This is also possible when not specifying either array as a literal, though the syntax gets a bit clunky in that case: ARRAY1+=(${ARRAY2[@]}).
32

Run it with bash:

bash test.sh

And seeing the error, it seems you're actually running it with dash:

> dash test.sh
test.sh: 5: test.sh: Syntax error: "(" unexpected

Only this time you probably used the link to it (/bin/sh -> /bin/dash).

6 Comments

Thanks! Runnning bash script.sh worked. But ... why even with #!/bin/bash it executes on dash? I typed export and my SHELL is set to bash.
Probably because of sh. You can see where it is pointing to with ls -l /bin/sh or readlink $(which sh). By the way, the quickest way to declare your array variable newlist based from your arguments is newlist=("$@"). Note that if args is "a b" "c" "d", without quotes ($@) it would split to 4 arguments when expanded ("a" "b" "c") due to word splitting whereas with "$@" the values remain as is with space.
The #! only works if you run it as a command - by making the file executable (chmod +x test.sh) and then just typing the filename without any sort of *sh in front of it: ./test.sh. If you explicitly type the name of a shell like sh or bash as the command to run, then that's the command that gets run; and to a shell, the #! line is just a comment.
@MarkReed Yes but I think he already meant that he ran the script with ./test.sh but dash is still the one that has executed
@konsolebox if that were the case it would have executed in bash, and it wouldn't matter what /bin/sh is linked to, because the shebang line has /bin/bash in it.
|
21

I find following syntax more readable.

declare -a <name of array>

For more details see Bash Guide for Beginners: 10.2. Array variables.

Comments

3

Try this to see if you are oriented to dash or bash

ls -al /bin/sh

If it says /bin/sh -> /bin/dash, then type this:

sudo rm /bin/sh
sudo ln -s /bin/bash /bin/sh

Then type again:

ls -al /bin/sh*

then must says something like this:

/bin/sh -> /bin/bash

It means that now sh is properly oriented to Bash and your arrays will work.

1 Comment

Thanks, I came across a similar issue but your answer helped me, still, the query remains. If I mention #!/bin/bash at the top of the script, then why dash comes into the picture while executing the shell script. I used ./tesh.sh to execute the script. Any explanation would be very helpful.
0
DOMAINS=(1); if [[ ${DOMAINS-} ]]; then # true
unset DOMAINS; if [[ ${DOMAINS-} ]]; then # false

Comments

-4

If the array is empty just do this:

NEWLIST=

You can check it with:

if [ $NEWLIST ] ; then
   # do something
fi

a non empty array declaration looks like this:

NEWLIST=('1' '2' '3')

To fill an array during process:

ARRAY=("$(find . -name '*.mp3')")

Hope this helps

6 Comments

NEWLIST has length 1 in that example. Try echoing ${#NEWLIST[@]} afterwards to see this.
ofc, thats normal but as my sample shows, the "if" will work as it should and show thats nothing inside. So the real test is if it exists, not for checking length, which will be 3 actually in my sample. Tetst it, and dont downvote something which works correctly
An empty array is one with length 0. NEWLIST is not an empty array, because it has length 1. I'm sorry, but you haven't answered the question correctly. Your if statement doesn't test for this properly.
In your opinion, an array of length 1 is "empty"?
i said, my sample is working well, and the test is also correct, the same test is going well for any variable. but anyway, i accepted your opinion, and though i will stop discussing. i also said, you r right, the way you test it, will return 1. But before you return length, you can test with [ var ].
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.