you have a comparison inside the while that every time it loops must be re-evaluated, very inefficient to do it that way
really except %i I dont use short var names like %a or %b as you stand a good chance of having a conflict.
you didnt use ( ) in the while loop, though you might be able to do that now in your version of mIRC there is no quarenty that you can shortcut that later or in other versions, so its probably a good habit to use the form shown in the help files.
I changed the %a = $readn in the script and that may be wrong, I didn't test this in any way.
Code:
on *:text:!change & &:#:{
  var %a = 1
  var %b = $lines(file.txt)
  while (%a <= %b) {
    var %line = $read(file.txt,ntw,$2,%a)
    var %line = $reptok(%line,$gettok(%line,2,32),$3,1,32)
    .write -l $+ $readn file.txt %line
    inc %a
  }
}