Reputation: 25
I have an ascii-file with the following structure:
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,3,0,0,0,0.04,0,0,990,0
1,0,3,0,0,0,0.12,0,0,3760,0
1,0,3,0,0,0,0.21,0,0,5372,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
.
.
.
The zeros stand for "random" numbers I need not to take care of.
Where column 3 is equal to 3 (always a block of three) I have to perform some calculations with the columns 7 and 10:
I need to calculate (0.04*990)+(0.12*3760)+(0.21*5372) and insert the result in column 5 of all three lines. The values in column 10 will be different in the next "block of three".
Previously I have done a lot ascii-file editing with awk, so if possible I would like to use it here also.
My main problem is to access the next two lines after finding column 3 = 3 and then to continue searching two lines further.
The result should look like this:
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,3,0,1618.92,0,0.04,0,0,990,0
1,0,3,0,1618.92,0,0.12,0,0,3760,0
1,0,3,0,1618.92,0,0.21,0,0,5372,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
1,0,4,0,0,0,0,0,0,0,0
.
.
.
I hope that I was able to describe the problem, if not just ask and I will clarify!
I tried:
awk -F"," '$3 == "3"' in.dat > out.dat
and to combine it with
awk -v "n=line numer" -v "s=string to insert" '(NR==n) { print s } 1' input-file
but my main problem is that I did not know how to access the fields after the first line and to use it in a formula for calculation.
The formula I really need to use is way more complex, but I only posted here a simple example because it is no problem to adapt it to a more complex solution.
Upvotes: 2
Views: 99
Reputation: 246807
awk's getline
command serves you well here
awk -F, -v OFS=, '
$3 == 3 {
c = 0
line1 = $0; c += $7 * $10; getline
line2 = $0; c += $7 * $10; getline
line3 = $0; c += $7 * $10
$0 = line1; $5 = c; print
$0 = line2; $5 = c; print
$0 = line3; $5 = c
}
{print}
'
That's not DRY enough for my tastes, but it's only 3 lines and pretty readable.
DRY Solution
awk -F, -v OFS=, '
$3 == 3 {
c = 0
for(i=1;i<=3;i++)
{line[i] = $0; c += $7 * $10; getline}
for(i=1;i<=3;i++)
{$0 = line[i]; $5 = c; print}
next
}1
'
Upvotes: 1
Reputation:
In awk
awk -F, '$3=="3"{a[++x]=$0;y+=($7*$10)}
!x
x==3{
while(++i<=x){
split(a[i],b,",")
b[5]=y
for(j=1;j<length(b);j++)
c=j>1?c","b[j]:b[j]
print c
c=t
}
x=y=i=0
}' file
a
and add the total to variable y
Shorter,less resource hungry way(credit to glenn jackmans answer for giving me the idea)
awk -F, '$3=="3"{a[++x]=$0;y+=($7*$10)}
!x
x==3{
while(++i<=x){
$0=a[i]
$5=y
print
}
i=y=x=0
}' test
Upvotes: 2