0

I am writing a shell script function that reads a given file and store the data into a 2D array.

File.txt

a1 b1 c1
a2 b2 c2
a3 b3 c3
# Let's just assume 3 rows

The idea is to pass the storage by reference using eval, with the function signature read_data File.txt array num_rows

read_data() {

  if [ ! -f $1 ]; then
    echo "Failed to read hosts ($1 not found)"; 
    exit;
  fi  

  while read -r line; do

    # skip the comments
    { [[ "$line" =~ ^#.*$ ]] || [[ -z $line ]] ;} && continue

    # Parse the line
    read -a tokens <<< $line

    if [ ${#tokens[@]} == 3 ]; then

      # Extract the user/host/home
      eval $2[\$$3, 0]=\${tokens[0]}
      eval $2[\$$3, 1]=\${tokens[1]}
      eval $2[\$$3, 2]=\${tokens[2]}
      eval $3=$(($3+1))

    else
      echo "Wrong line format '$line'"
    fi  

  done < $1
}

After calling below

declare -a array
num_rows=0
read_data File.txt array num_rows

What I get is num_rows equals to 3 but the contents stored in array is

pnt_data() {
  for ((i=0; i<$2; i++)); do

      eval a=\${$1[$i, 0]} 
      eval b=\${$1[$i, 1]} 
      eval c=\${$1[$i, 2]} 

      echo $a $b $c
  done
}

pnt_data array num_rows

a3 b3 c3
a3 b3 c3
a3 b3 c3

What happen to this? Is there anything wrong with my function?

1
  • Bash does not support 2D arrays, choose a different language. awk kinda supports them. Personally I would consider Perl or Python. Commented Aug 17, 2016 at 18:37

1 Answer 1

4

Array indices are evaluated in an arithmetic context, and the comma operator works by evaluating the left-hand operand, ignoring it, then evaluating to the right-hand operand. For example:

$ echo $((3,0))
0
$ echo $((3+9,0))
0
$ echo $((a,0))
0

As a result, all of the following assignments are equivalent to foo[0]=bar:

foo[3,0]=bar     # ignore 3
foo[3+9,0]=bar   # 3+9=12, ignore 12
foo[a,0]=bar     # ignore whatever the value of a is

If you want to simulate multidimensional indices, you'll need to use an associative array, so that the string used as an index does not undergo arithmetic expansion before using it.

declare -A array  # capital A, not lowercase a
num_rows=0
read_data File.txt array num_rows
Sign up to request clarification or add additional context in comments.

1 Comment

can u elaborate it more?

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.