just wrote it up quickly.

Way to quickly i think.
Your doing a wild search and not using "& & $2" to match the data3 items so it wont ever match (below assumes thats fixed)
Your replacement method is dodgy, it well replace data1 should it match data2, with newdata2
Your jump ahead to last line searched needed to move ahead to last line searched + 1, else it well locate a match on last line searched again
The while condition is unlikely to ever exit as should a line not be matched $readn well be 0 and thus trap %a line count of the file.

My orginal code I must admit was un checked also, i wrote it right here, however due to its small size I was pretty sure it would work, (it would of if he was using mirc 6.16 which is his fault for not mentioning he wasnt) However admittedly it doesnt cater for more than one line matching, I assumed the file had unque data3 fields, whcih might have been wrong, so i submit this to replace it.

on *:TEXT:!change & &:*:{ change $2 $3 }
alias change {
var %i = $read(txtfile.txt,nt,1), %i = 1
while (($readn) && ($read(txtfile.txt,ntw,& & $1,%i))) { write $+(-l,$readn) txtfile.txt $puttok($ifmatch,$2,2,32) | var %i = $readn | inc %i }

* i well admit its untested code so there might be an error in it *

PS: the inital $read of the file is to load up $readn to a none zero state