Filling in the missing data point by awk

I am learning AWK by trying out examples whenever I need a specific conversion. I would like to edit the 'before.txt' so that all the missing data points between 140-150 are added and shown as 0.

before.txt

145 2
148 13
149 17

to below,

140 0
141 0
142 0
143 0
144 0
145 2
146 0
147 0
148 13
149 17
150 0

And here is what I tried so far.

awk 'BEGIN { for (i = 140; i <= 150; ++i){if(i=$1) print $i,$1;else print $i,0}}' before.txt

Any help would be great

Try

awk 'NR == FNR {T[$1] = $2; next} END {for (i=140; i<=150; i++) print i, (i in T)?T:0}' file
140 0
141 0
142 0
143 0
144 0
145 2
146 0
147 0
148 13
149 17
150 0
1 Like

You do something in the BEGIN section, before the before.txt is processed.
And then you do nothing in the main section (where it's too late anyway).
The solution is to process the file in the main section and store it into variables (An array that is addressed by the $1 values), and then process/print in the END section. Like RudiC did.
The following is multi-line for readability (at least for me), and does not have the NR==FNR {...; next} overhead (that takes the first given file, where the following code will take the next file(s) - but here is only one file).

awk '
# main section; process all lines of all given files
{ T[$1]=$2 }
END {
  for (i=140; i<=150; ++i) {
    if (i in T) print i,T; else print i,0
  }
}' before.txt

It prints with an explicit if - else, like you did; compare with RudiC's implicit if!

2 Likes

Hello numareica,

Welcomes to forums, special thanks for using the code tags. Could you please try following and let me know if this helps.
1st: If you need to have maximum number till 150 only from 140 then following may help you.
Let's say following is the Input_file:

140 2
148 13
149 17
152 28
153 20
awk -vSTART=140 -vend=150 'NR==1{if(START < $1){while(START <= $1){if(START==$1){print;Y=$1;next} else {print START++ OFS 0}}};if(START==$1){print;Y=$1};next}{if($1 - Y > 1){while(Y<end && ++Y <= $1){if(Y==$1){print;Y=$1;;next} else {print Y OFS 0}}} else {print $0;Y=$1}}'   Input_file

Output will be as follows.

140 2
141 0
142 0
143 0
144 0
145 0
146 0
147 0
148 13
149 17
150 0

EDIT: Adding 1st solution's non-one liner form now.

awk -vSTART=140 -vend=150 'NR==1{
                                        if(START < $1){
                                                        while(START <= $1){
                                                                                if(START==$1){
                                                                                                print;
                                                                                                Y=$1;
                                                                                                next
                                                                                             }
                                                                                else         {
                                                                                                print START++ OFS 0
                                                                                             }
                                                                          }
                                                      };
                                        if(START==$1) {
                                                        print;
                                                        Y=$1
                                                      };
                                        next
                                }
                                {
                                        if($1 - Y > 1){
                                                        while(Y<end && ++Y <= $1)            {if(Y==$1){
                                                                                                        print;
                                                                                                        Y=$1;
                                                                                                        next
                                                                                                       }
                                                                                              else     {
                                                                                                        print Y OFS 0
                                                                                                       }
                                                                                             }
                                                      }
                                        else          {
                                                        print $0;
                                                        Y=$1
                                                      }
                                }
                         '  Input_file
 

2nd: If you need to run the commands till the last maximum number starting from 140 then following may help you in same. But in case maximum number is lesser than value of 150 then it will take care of printing the values till 150 .
Let's say following is the Input_file:

145 2
148 13
149 17
152 28
153 20
176 2
190 0

Then following is the code for above:

awk -vSTART=140 -vend=150 'NR==1{if(START < $1){while(START <= $1){if(START==$1){print;Y=$1;next} else {print START++ OFS 0}}};if(START==$1){print;Y=$1};next}{if($1 - Y > 1){while(++Y <= $1){if(Y==$1){print;Y=$1;;next} else {print Y OFS 0}}} else {print $0;Y=$1}} END{;if(end>Y){while(Y < end){print ++Y OFS 0;}}}'   Input_file

Output will be as follows then.

140 0
141 0
142 0
143 0
144 0
145 2
146 0
147 0
148 13
149 17
150 0
151 0
152 28
153 20
154 0
155 0
156 0
157 0
158 0
159 0
160 0
161 0
162 0
163 0
164 0
165 0
166 0
167 0
168 0
169 0
170 0
171 0
172 0
173 0
174 0
175 0
176 2
177 0
178 0
179 0
180 0
181 0
182 0
183 0
184 0
185 0
186 0
187 0
188 0
189 0
190 0

EDIT: Adding a non-one liner form of 2nd solution now.

awk -vSTART=140 -vend=150 'NR==1{
                                        if(START < $1){
                                                        while(START <= $1){
                                                                                if(START==$1){
                                                                                                print;
                                                                                                Y=$1;
                                                                                                next
                                                                                             }
                                                                                else         {
                                                                                                print START++ OFS 0
                                                                                             }
                                                                          }
                                                      };
                                        if(START==$1) {
                                                        print;
                                                        Y=$1
                                                      };
                                        next
                                }
                                {
                                        if($1 - Y > 1){
                                                        while(++Y <= $1)   {
                                                                                if(Y==$1)    {
                                                                                                print;
                                                                                                Y=$1;;
                                                                                                next
                                                                                             }
                                                                                else         {
                                                                                                print Y OFS 0
                                                                                             }
                                                                           }
                                                      }
                                        else          {
                                                        print $0;
                                                        Y=$1
                                                      }
                                                      }
                          END    {;
                                        if(end>Y)     {
                                                        while(Y < end)     {
                                                                                print ++Y OFS 0;
                                                                           }
                                                      }
                                 }
        ' Input_file
 

Thanks,
R. Singh

1 Like

Absolutely right - I started "the usual way" and overlooked the "one file only" ... rats!

Worked like a charm! thanks!