Kay
Kay

Reputation: 2067

loop with multiple columns in shell

I have a file with three columns (ID number, x, y)

ifile.txt
1      32.2    21.4
4      33.2    43.5
5      21.3    45.6
12     22.3    32.5
32     21.5    56.3
43     33.4    23.4
44     23.3    22.3
55     22.5    32.4

I would like use ID numbers as a loop so that is will read like

when ID=1, then x=32.2, y=21.4
when ID=4, then x=33.2, y=43.5
and so on

I have done as follows, but it seems a lengthy way.

id1=1   #ID number
id2=$(wc -l < ifile.txt)   #total number of IDs
while [ $id1 -le $id2 ]
do
ID=$(awk 'NR=='$id1' {print $1}' ifile.txt)
x=$(awk 'NR=='$id1' {print $2}' ifile.txt)
y=$(awk 'NR=='$id1' {print $3}' ifile.txt)
#
#here I want to do some computation using ID, x and y
#e.g. with each ID, I will execute a program by changing its corresponding x and y values
#for instance
echo $ID $x $y
(( id1++ ))
done

I need to short it and a convenient way.

Upvotes: 0

Views: 927

Answers (2)

Jonathan Leffler
Jonathan Leffler

Reputation: 753515

Superficially, you could use:

while read ID x y
do
    case "$ID" in
    …
    esac
    echo "$ID $x $y"
done < ifile.txt

where the case might, or might not, be an appropriate method for deciding what action to take as a line is read.

I used read without the -r because the code is going to have heebie-jeebies if the data contains characters (backslashes) that would be affected by the presence or absence of -r. Neither is going to be especially reliable. You can judge otherwise and use -r and thereby satisfy the "thou shalt use -r" brigade.

Note that this reads the file once where your code reads the file three times for each line in the file. That's an O(N2) algorithm where an O(N) algorithm is appropriate.

If your computations are complex enough, you'd do better using a more powerful language than the shell. You could consider awk or Perl or Python (or numerous other languages) instead.

Upvotes: 3

John1024
John1024

Reputation: 113814

This reads each line and does a computation on x and y (you didn't say what computation, so I made one up):

$ awk '{printf "ID=%2s: x+y*y=%7.2f\n",$1,$2+$3*$3;}' ifile.txt 
ID= 1: x+y*y= 490.16
ID= 4: x+y*y=1925.45
ID= 5: x+y*y=2100.66
ID=12: x+y*y=1078.55
ID=32: x+y*y=3191.19
ID=43: x+y*y= 580.96
ID=44: x+y*y= 520.59
ID=55: x+y*y=1072.26

In other words, awk has more better math support than shell. If you want to do calculations, do it all in awk.

Upvotes: 3

Related Questions