3

Say we have a BASH array with integers:

declare -a arr=( 1 2 3 )

and I want to do an arithmetic operation on each element, e.g. add 1. Is there an altenative to a for loop:

for (( i=0 ; i<=${#arr[@]}-1 ; i++ )) ; do
    arr[$i]=$(( ${arr[$i]} + 1 ))
done

I have tried a few options:

arr=$(( ${arr[@]} + 1 ))

fails, while

arr=$(( $arr + 1 ))

results in

echo ${arr[@]}
2 2 3

thus only the first (zeroth) element being changed.

I read about awk solutions, but would like to know if BASH arithmetics support such batch operations on each array element.

6
  • 2
    I don't think there is an alternative. As a side note, none of the programming languages I use can do that natively. Also, you can simplify arr[$i]=$(( ${arr[$i]} + 1 )) to arr[$i]++ Commented Jul 30, 2015 at 7:58
  • 1
    I do not know about your preferred languages, but e.g. FORTRAN does support arr(:) = arr(:) + 1 or arr3(:) = arr1(:) * arr2(:) , so I had the hope that BASH would be capable. Sorry, I cannot reproduce the arr[$i]++ thing. Care to explain? Commented Jul 30, 2015 at 8:06
  • 1
    forgot the parenthesis. correct syntax is (( $arr[$i]++ )) Commented Jul 30, 2015 at 8:19
  • The shell would only be looping in the background anyway if there were a function. So if it bothers you just write your own function to do it. Commented Jul 30, 2015 at 9:02
  • @Plutox sorry, still cannot reproduce, could you explicitly write the for loop start to end? Thanks in advance. Commented Jul 30, 2015 at 9:17

2 Answers 2

4

I know your question is not fresh new but you can accomplish what you want by declaring your array as integer and then applying a substitution:

declare -ia arr=( 1 2 3 )
value=1

declare -ia 'arr_added=( "${arr[@]/%/+$value}" )'
echo "arr_added: ${arr_added[*]}"

value=42
declare -ia 'arr_added=( "${arr[@]/%/+$value}" )'
echo "arr_added: ${arr_added[*]}"

It outputs:

arr_added: 2 3 4
arr_added: 43 44 45

You can perform other math operations as well:

value=3
declare -ia 'arr_multd=( "${arr[@]/%/*$value}" )'
echo "arr_multd: ${arr_multd[*]}"

Outputs:

arr_multd: 3 6 9
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you - in my tests also works without using quotes, e.gg declare -ia new_arr=( ${arr[@]}/%/+$value }. Is there any documentation regarding this? I didn't see it in man bash.
Yes, there is no direct mention for -i in array documentation neither in any man page nor TLDP or the like. You can check -i, though in "Typing variables: declare or typeset" [tldp.org/LDP/abs/html/declareref.html]. It works for any variable, including arrays.
-1

you can use eval to have the feeling of lambda function (not sure about the syntax but this should be the main idea ) :

eval "function add1 { x=$1; y=$((x+1)) ; return $y; }"
for (( i=0 ; i<=${#arr[@]}-1 ; i++ )) ; do
    add1 ${arr[i]}
done

2 Comments

I don't think this answers the question. OP wants to avoid a for loop altogether
It also is a pointless use of eval, since the parameter expansions will be expanded before the function is ever defined. return is used to return an exit status, not a computation.

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.