0

I'm struggling to pass a multi-row array of floating-point numbers through a for loop, have it run a calculation, then define a new variable from the outputs.

Here's a simplified version of my Bash:

inputs=$(echo "12.12
34.34")

New_array=$( for var in "${inputs[@]}"; do
                 echo "${var}*2"| bc -l;
             done )

I would expect the result from echo "$New_array" to be this:

$ echo "$New_array"
24.24
68.68

But I get this?

$ echo "$New_array"
12.12
68.68

Or whilst I've been troubleshooting (e.g. removing the $New_array variable):

(standard_in) 1: syntax error

I believe the problem has something to do with line return being read as an input for the first loop? But the solutions I've tried haven't worked so far.

Where am I going wrong?

9
  • 1
    You have no arrays in that code... Commented Jan 15, 2022 at 4:32
  • Can you add the command you use to run the script? Commented Jan 15, 2022 at 4:38
  • @kpie, just bash scriptname.sh? I've only been debugging this in the terminal if that helps? Commented Jan 15, 2022 at 6:07
  • 1
    Neither of your variables is actually an array, they're both just strings with a newline in the middle (making them two lines of text), but the way you're looping over inputs requires it to be an actual array. See this question, and this one on the Unix&Linux SE. Do you actually want to use arrays (generally cleaner), or multiline strings? BTW, $(echo something) is almost always a mistake -- the $( ) and echo basically cancel each other out. Commented Jan 15, 2022 at 6:24
  • 1
    @KyranMcDonnell Some other notes: if you aren't using an actual array, you should remove the [@] (i.e. use $inputs or ${inputs} instead of ${inputs[@]}). Also, beware that using unquoted variables will cause anything that looks like a filename wildcard to expand into a list of matching filenames, e.g. in 2 * 3, the * will be replaced by a list of filenames in the current directory. This is one of the reasons that actual arrays are preferred. Commented Jan 15, 2022 at 7:36

1 Answer 1

0

This is probably what you are trying to do:

#!/bin/bash

inputs=(12.12 34.34)

for var in "${inputs[@]}"; do
    New_array+=("$(bc -l <<< "$var * 2")")
done
printf '%s\n' "${New_array[@]}"

Note that inputs=(12.12 34.34) creates an array named inputs having elements 12.12 and 34.34. New_array+=(...) appends an element (here, the output of the command bc -l <<< "$var * 2") to the array New_array. Alternatively, this could be done at once using printf's implicit loop and mapfile builtin of bash:

mapfile -t New_array < <(printf '%s * 2\n' "${inputs[@]}" | bc -l)

If it is guaranteed that the elements of the array don't contain whitespace and glob characters (this is probably the case here), then this could be an alternative way:

New_array=($(printf '%s * 2\n' "${inputs[@]}" | bc -l))
Sign up to request clarification or add additional context in comments.

Comments

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.