2

I have the following shell script. The problem I am facing is that in the first iteration ${NUM[${i}]} returns the whole content of the array and every following iteration returns empty. Why is that so?

NUM="2 2 2 0"
i=0
    for CLIENT in ${BAG_CLIENTS} ; do
        if [ "$BFT" = true ]; then
          SERVERS="-$i"
        fi
        echo "Starting ${NUM[${i}]} clients with $PERCWRITES writes and $SERVERS serv$
        ssh rneiheiser@$CLIENT "~/runclient.sh $i ${NUM[${i}]} $PERCWRITES $SERVERS &$
        ((i++))
    done
4
  • 1
    That's not an array. An array would be num=( 2 2 2 0 ) Commented Sep 12, 2017 at 16:16
  • And that's a really buggy way to pass arguments to ssh, though addressing the issue would be out-of-scope of the individual question. Basically -- ssh munges all its arguments together into a single string, and passes that string for execution by a remote shell. If you want to maintain control over how things are parsed by that remote shell, the proper practice is to build an single eval-safe string locally and pass it as a single argument. Commented Sep 12, 2017 at 16:19
  • BTW, all-caps variable names are used for variables with meaning to the OS and shell -- your own variables should use names with at least one lowercase character to avoid conflicts. See relevant POSIX spec @ pubs.opengroup.org/onlinepubs/9699919799/basedefs/…, fourth paragraph, reserving lowercase names for application use. Commented Sep 12, 2017 at 16:25
  • (When I say "buggy", that includes security bugs -- if you're passing, say, a comment string, a password, a filename, &c. provided by a user as one of your arguments, you don't want any $(rm -rf ~) inside that comment to be parsed by the remote shell as code). Commented Sep 12, 2017 at 16:28

1 Answer 1

7

You aren't defining an array at all -- you're defining a string.

When an array is accessed as a string, only its first item is returned. That is to say:

array=( "first item" "second item" )
echo "$array" ## echos only "first item"

When a string is accessed as an array, it acts like a single-element array, with only its first element.

string="first item"
echo "${string[0]}" # also echos "first item"

If you want to define an array and access it as an array, the syntax looks like:

array=( "first item" "second item" "third item" )
echo "${array[0]}" # "first item", again.

# iterate over each element in turn
for item in "${array[@]}"; do
  echo "Iterating over array element $item"
done

...after which you can either expand to all the items with "${array[@]}", iterate over the indices with "${!array[@]}", or access an individual one with ${array[$idx]} (where $idx is your index number).

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

5 Comments

is there also a way to retrieve the data from the string in a similar manner like that? I'd like to receive this string as a command line argument
You can read it into an array. read -r -a arrayname <<<"$string"
...that said, that's only a reasonable approach if the restrictions on your array's potential contents are such that you have separator character(s) that can't possibly appear inside the elements themselves. Otherwise, you'll want a separate command-line argument for each element. It's common practice to pass -n foo -n bar to specify two array elements, foo and bar, for instance.
the array syntax does only work in bash (/bin/bash) not in sh (/bin/sh)
@KargWare, right; sh doesn't support arrays at all. If one wants arrays, it's obligatory to use a shell (like ksh, bash, or zsh) that actually supports arrays.

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.