0

Say I have these bash functions in a script:

foo(){
  my_args_array=("$@")
  export my_args="${my_args_array[@]}"
  bar $my_args
}

bar(){
  echo "number of args: $#";
}


foo a b 'c d e'

if I run the above script, I will get:

number of args: 5

but what I am looking for is:

number of args: 3

so my question is - is there a way to map the value returned by my_args_array[@], so I can surround each element with single quotes? Or do whatever I need to do to make the env variable string look like the original command line arguments.

2
  • What do you want to do in the end? You say you want to turn the array into a string, but in the code you're passing it as an argument to a function, and talk about the number of args the function gets. So, do you really want the string, or do you want the array elements passed to a command as distinct arguments? If you have a more concrete use-case to present, it might help in suggesting an appropriate solution.
    – ilkkachu
    Jun 19, 2018 at 20:01
  • I want the argument c d e to remain as a single arg, not 3 args. Jun 19, 2018 at 20:01

2 Answers 2

3

Use an array, not a string:

#!/bin/bash
foo(){
  my_args=("$@")
  bar "${my_args[@]}"
}

bar(){
  echo "number of args: $#";
}


foo a b 'c d e'
4
  • Does Bash export arrays?
    – user147505
    Jun 19, 2018 at 20:02
  • @Tomasz, no, it doesn't.
    – ilkkachu
    Jun 19, 2018 at 20:03
  • This looks like it works great, thanks. @Kusalananda can you mention if this solves the original problem to a better extent? If someone could save my ass by supporting OP, I think this is a legit question. Jun 19, 2018 at 20:04
  • 3
    @AlexanderMills This solves the original problem in your other question in exactly the same way as I showed in my answer there: By passing the array's values on the command line. The only difference is that choroba is using an array to hold the values of $@ and then passes the quoted values. He could have done bar "$@" directly.
    – Kusalananda
    Jun 19, 2018 at 20:07
3

In Bash, using "${array[@]}" (or "$@") in the right hand side of an assignment works a bit like ${array[*]} (or "$*"): it joins the array elements to a single string, using spaces as separators. (${array[*]} ("$*") uses the first character (byte?) of IFS.) This also applies to arguments of export, declare, local etc.

Then you have a b c d e in my_args, and the unquoted expansion splits.

If you want an array, use an array:

foo() {
    bar "$@"
}
bar() {
    echo "number of args: $#";
}
foo a b 'c d e'

Or, if you want a string, it's probably better to explicitly use "${array[*]}" for clarity.

(FWIW, Bash doesn't support exporting arrays through the environment [1] [2])

2
  • Sorry, my eyes skipped past the "in an assignment" bit. You are correct.
    – Kusalananda
    Jun 19, 2018 at 20:20
  • 1
    @Kusalananda, but you're right, it's not really documented what happens. I posted a bug report on it a while ago, maybe it'll show up eventually. (Sadly, I don't think the online manual has been updated in a while.)
    – ilkkachu
    Jun 19, 2018 at 20:23

You must log in to answer this question.

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