1

I need to store a string that may include special characters (to be exact: *) into an array as individual strings. The string is returned by a function so at the point of the array declaration I do not know its contents

foo(){
    in="my * string"
    echo "$in"
}
arr=($(foo))

What I've already tried was:

arr=("$(foo)")

where * doesn't get expanded but the array consists of 1 string, and:

arr=($(foo | sed -r "s/[\*]/'*'/g"))

that replaces each occurence of * with the string: *. Which is not what I want to achieve. What I aim for is just storing each * from the returned string as *.

4
  • 1
    You put the quotes in the wrong place. arr=("$(foo)"). Quoting the parentheses prevents this from being an array assignment. Commented Apr 25, 2019 at 14:07
  • @chepner You're right - but it's just a typo in my post, though. Commented Apr 25, 2019 at 14:54
  • So you want array=("my" "*" "string") in the end? Commented Apr 25, 2019 at 15:07
  • Yes. I probably should have included a desired result example in my original post. Though my problem is already solved. Commented Apr 25, 2019 at 19:42

2 Answers 2

2

Storing an array this way does not expand the "*"

ins="my * string"
read -r -a array <<< "$ins"
echo "${array[*]}"
Sign up to request clarification or add additional context in comments.

2 Comments

arg. You posted while I was typing an answer and I didn't see that you already had it, lol
Thanks a lot! You and @PaulHodges just saved my homework. :)
0

Short answer:

 read -a arr <<< "$(foo)"

To elaborate -

Your function is correctly returning the single string "my * string". Your assignment to an array executes the function in unquoted context, so the asterisk is evaluated and parsed to the names of everything in the directory.

Putting quotes around the outer parens makes the whole assignment into the string "(my * string)" - also not what you want. You need something that preserves the asterisk unexpanded into directory contents but parses the elements of the string into separate items in your array, yes?

 read -a arr <<< "$(foo)"

This passes back the string properly quoted, and then reads it into the array after splitting with $IFS, so each item becomes an unexpanded string in the array.

$: echo "${#arr[@]}"
3
$: printf "%s\n" "${arr[@]}"
my
*
string

3 Comments

You understand what was happening and why this fixes it? Any questions?
I almost understand what was happening. arr="($(foo))" was a typo and I still don't really get why arr=("$(foo)") would return an array with one element instead of splitting whatever's inside the double-quotes into separate strings using IFS.
$(foo) replaces itself with the output of the foo function, which is "my * string". If you call it in a nonquoted context it's just like passing it as arguments to echo unquoted, which expands the *. Putting quotes around it ("$(foo)") is just like putting quotes around it when passing to echo again, and makes it one string. It's exactly like saying arr=( "my * string" ), which assigns one element to your array.

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.