3

I'm trying to pass a string to a function. The string contains multiple arguments and some of the arguments may begin with multiple spaces.

#!/bin/bash
test_function() {
    echo "arg1 is: '$1'"
    echo "arg2 is: '$2'"
    echo "arg3 is: '$3'"
}

a_string="one two \"  string with spaces in front\""
result=$(test_function $a_string)
echo "$result"

Here is the output actually produced:

arg1 is: 'one'
arg2 is: 'two'
arg3 is: '"'

Here is an example of the output I am trying to achieve:

arg1 is: 'one'
arg2 is: 'two'
arg3 is: '  string with spaces in front'

How can I store arguments containing spaces in a string like this to later be passed to a function?

Although it can be done with an array, I need to first convert the string into the array values.

2 Answers 2

3

With an array.

a_string=(one two "  string with spaces in front")
result=$(test_function "${a_string[@]}")
Sign up to request clarification or add additional context in comments.

4 Comments

the problem is that i would need to first convert the string into the array values. an_array=("$a_string") how can this be done?
You don't. You use an array to begin with.
easier said than done in the actual application. it gets passed through multiple functions and manipulated along the way.
It requires a bit more work, but you can pass the name of the array as an argument, and use indirect access. In some cases, simply passing the elements as positional parameters (with $@) works well, it is not an array but works similarly.
0

bash -c may be what you're looking for (or perhaps even better, eval, as John Kugelman points out below). From the man page,

If the -c option is present, then commands are read from the first non-option argument command_string. If there are arguments after the command_string, the first argument is assigned to $0 and any remaining arguments are assigned to the positional parameters. The assignment to $0 sets the name of the shell, which is used in warning and error messages.

Basically bash -c "foo" is the same (plus a subshell) as foo. In this way we can easily insert our string as arguments.

Here it is in your example:

#!/bin/bash
test_function() {
    echo "arg1 is: '$1'"
    echo "arg2 is: '$2'"
    echo "arg3 is: '$3'"
}

a_string="one two \"  string with spaces in front\""

export -f test_function
bash -c "test_function $a_string"

(The export is necessary in this example because it's a defined function, but wouldn't be in other cases).

Output:

arg1 is: 'one'
arg2 is: 'two'
arg3 is: '  string with spaces in front'

1 Comment

eval is simpler, and executes in the current shell rather than a subshell. I don't recommend it nor bash -c, though. Ignacio's advice to use an array is the way to go. One should simply never store multiple words in a string like this. No point in trying to unmangle mangled data; just avoid mangling it in the first place.

Your Answer

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