2

In the example below, why does $var get passed to the su in the start function, but not the array modules ?

#!/bin/bash
var=cat
modules=(
one
two
three
four
)

start() {
    su gleventh -c "for i in ${modules[@]}; do echo -- $i -- $var;  done"
}

$1

echo "out of function"
for i in ${modules[@]}; do echo -- $i -- $var;  done

The script above returns:

$ sudo ./test.sh start
-- -- cat
-- -- cat
-- -- cat
-- -- cat
out of function
-- one -- cat
-- two -- cat
-- three -- cat
-- four -- cat
2

The problem was that since the su statement was in double quotes, the variables were all expanded before the su command was called, which means $var becomes "cat" but $i becomes "" since it was not defined. Bash doesn't know that it was supposed to be an iterator variable, it just expands it to a NULL string. The answer is to escape that "$" like so:

#!/bin/bash
var=cat
modules=(
one
two
three
four
)

start() {
    su gleventh -c "for i in ${modules[@]}; do echo -- \$i -- $var;  done"
}

$1

echo "out of function"
for i in ${modules[@]}; do echo -- $i -- $var;  done
  • Strange. I'm getting two: -c: line X: syntax error: unexpected end of file – choroba Mar 4 '15 at 15:20
  • You copied it verbatim? (and changed the gleventh to a valid user) – Gregg Leventhal Mar 4 '15 at 15:22
  • Yes. BASH_VERSION=4.2.53(1)-release, OpenSUSE 13.1. – choroba Mar 4 '15 at 16:30
  • My guess is the encoding in the quotes is different from whatever you used to edit with. I would go back and manually replace all of the double quotes by hand and run it again. – Gregg Leventhal Mar 4 '15 at 21:18
  • Pardon? ${var[@]} should do word splitting according to the documentation (see man bash). – choroba Mar 5 '15 at 0:13
1

The special parameter ${array[@]} in double quotes causes word splitting if the array has more than one member:

$ for word in "for i in ${arr[@]} ; do" ; do echo "$word" ; done
for i in a
b
c ; do

If your modules' names don't contain spaces, you can have more luck using the * subscript:

$ for word in "for i in ${arr[*]} ; do" ; do echo "$word" ; done
for i in a b c ; do
  • The elements of the array are "one two three four" no spaces. Using ${ [*]} didn't make any difference, I see no element of the array when using su. – Gregg Leventhal Mar 4 '15 at 14:56
  • @GreggLeventhal: Did you replace the @ in double quotes, right? – choroba Mar 4 '15 at 14:59
  • 1
    I figured it out, the answer for me was to put the iterator variable "$i" with an escape like "\$i" – Gregg Leventhal Mar 4 '15 at 15:00
  • The problem was that $i was being evaluated before the su command was run, so instead of being the iterator variable in the su statement, it had already evaluated to a blank string since $i was not defined. – Gregg Leventhal Mar 4 '15 at 15:03
  • @GreggLeventhal: You're right. Does it work with a @, though? – choroba Mar 4 '15 at 15:06

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.