1

how to pass 2d array to function in shell script ? i need to pass matrix to function but it do not work

tr(){
matrix="$3"
num_rows="$1"
num_columns="$2" 
f1="%$((${#num_rows}+1))s"
f2=" %9s"
for ((i=1;i<=num_rows;i++)) do
for ((j=1;j<=num_columns;j++)) do
    echo  -ne "${matrix[$i,$j]}\t"
  done
echo -e "\n"
done 


tr $rows $columns $x
4
  • 1
    Bash only supports 1d arrays, so you'll have to implement your own multi-dimensional indexing scheme. Commented Dec 30, 2014 at 14:40
  • how could do it in bash ? Commented Dec 30, 2014 at 14:41
  • Anything you can do in a 2d array you can do in a 1d one with a bit of work. Commented Dec 30, 2014 at 15:59
  • That's good old FORTRAN logic, Jidder - the only useful data structure is an array. Everything else can be achieved as well by appropriate usage of arrays. Commented Dec 30, 2014 at 16:06

1 Answer 1

4

Use an associative array:

declare -A matrix

Then things like matrix[6,7]=42 will work because "6,7" ist just a string, and associative arrays accept strings as indices. You might as well write things like

matrix[one,two]=three
matrix[yet,another,dimension]="Perry Rhodan"

You can just write any string between [ and ]. Here is a complete example for how to use it.

#!/bin/bash
#
# Example for a function that accepts the name of an associative array ...
# ... and does some work on the array entries, e.g. compute their sum
# We assume that all *values* of the array are integers - no error check

sum() {
   local s=0                 # we don't want to interfere with any other s
   declare -n local var="$1" # now var references the variable named in $1
   for value in "${var[@]}"  # value runs through all values of the array 
   do
      let s+="$value"
   done
   echo sum is $s
}

declare -A m  # now m is an associative array, accepting any kind of index

m[0,0]=4      # this looks like 2-dimensional indexing, but is is not
m[2,3]=5      # m will accept any reasonable string as an array index
m[678]=6      # m does not care about the number of commas between numbers
m[foo]=7      # m does not even care about the indices being numbers at all

sum m

As you see, the matrix m not really has 2 dimensions. It just takes any string as an index, as long as it does not contains certain shell syntax characters, and comma is allowed in the string.

Please note the reference declare -n ... - this allows simple access to the matrix from within the function and, most important, without knowing the name of the matrix. Thus you can call that function for several matrices with different names.

The keyword local is important. It means that, upon return, var is unset automatically. Otherwise you will have a reference "var" to an associative array. If you ever want to use var later, it will be hard to use it because you cannot use it as anything else but an associative array. And if you try to get rid of it by "unset var", bash will kindly remember that var refers to m, and delete your matrix m instead. In general, make variables in functions be local wherever possible. It even allows me to re-use a name. For example, using "s" as a variable name inside a function may appear dangerous because it might change the value of a global variable "s". But it doesn't - by declaring it local, the function has its own private variable s, and any s that might already exist is untouched.

Just as a demonstration: If you want to see the array indices in the loop, do this:

sum() {
   local s=0                 # we don't want to interfere with any other s
   declare -n local var="$1" # now var references the variable named in $1
   for i in "${!var[@]}"     # !var means that we run through all indices 
   do                        # we really need a reference here because ...
      let s+=${var["$i"]}    # ... indirections like ${!$1[$i]} won't work
   done
   echo sum is $s
}
Sign up to request clarification or add additional context in comments.

2 Comments

This is true, but then how would you pass it to a function?
wow, you have a short number! Wait a moment, I'll add that to my answer.

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.