I've got a text file containing two columns, like so:

26 0.000342231
27 0.000342231
28 0.000684463
29 0.00136893
30 0.00102669
31 0.00308008
32 0.00308008
33 0.00444901
34 0.00718686
35 0.00718686
36 0.0109514
37 0.0123203

I'd like to loop over the text file and store each columns value to an associative array - something like a dictionary. If possible I'd like to keep data types of values in each column (int and float).

For a calculation I then need to sum up 2nd column's values for a particular interval till the end of the file, e.g. "sum up 29's (1st column) associated value (0.00136893) down to the last associated value"

What's the best way to do so? Bash and python solutions are most welcome!

  • 1
    awk '{my_array[$1]=$2}END{for(i=29;i<=NR;i++)my_sum+=my_array[i];print my_sum}' text.file – Costas Aug 11 '15 at 10:24

edit, I misread the question and answered something you weren't asking. Did you want the column entries to be the dictionary keys? So you can check for duplicates when more data arrives? If not, you don't need an associative array, just normal indexed. That will let you start from wherever.

Bash doesn't do FP math at all, so having the data in a bash array isn't useful. >.<

If you want integer indices, and the indices can't be negative, then you should use an indexed array, not an associative (string-indexed) array.

Use a while read loop to parse the input into two variables, then set an array with them.

declare -a arr
# declare -A arr  # associative

while read c1 c2 leftovers;do
done < file.txt

echo "arr[4] == ${arr[4]}"

You don't actually need declare -a, you can just start using it. Also note that "${#arr}" is the number of set element in the array, not necessarily the last index. (use arr[-1] to access the last element.) "${!arr[@]}" is the list of indices (keys).

All the other things from the bash manual work, too, of course.


with bash:

arr1=( $( cut -d' ' -f1 file ) )
arr2=( $( cut -d' ' -f2 file ) )

i.e. cut -field 1 (or 2) using space as -delimiter and assign the output to an array.

bash does not distinguish data types in variables, the first index number for any array is 0.

Sum with bash and bc

echo ${arr2[@]} | sed 's/ /+/g' | bc -l

i.e. print all array elements (with space as separators), replace spaces with '+', send to bc -l for doing the actual math operation.

  • This is reading the file twice, isn't it? – Jason Aug 11 '18 at 15:02
  • It is. Also not too effective but OP preferred bash solutions. I'd strongly suggest awk for such column-based jobs. – FelixJN Aug 12 '18 at 19:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.