map array of arguments and then convert to string

6,792

Solution 1

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'

Solution 2

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])

Share:
6,792
Alexander Mills
Author by

Alexander Mills

Updated on September 18, 2022

Comments

  • Alexander Mills
    Alexander Mills over 1 year

    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.

    • ilkkachu
      ilkkachu almost 6 years
      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.
    • Alexander Mills
      Alexander Mills almost 6 years
      I want the argument c d e to remain as a single arg, not 3 args.
  • Admin
    Admin almost 6 years
    Does Bash export arrays?
  • ilkkachu
    ilkkachu almost 6 years
    @Tomasz, no, it doesn't.
  • Alexander Mills
    Alexander Mills almost 6 years
    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.
  • Kusalananda
    Kusalananda almost 6 years
    @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.
  • ilkkachu
    ilkkachu almost 6 years
    @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.)