'>>' opens the file in *append* mode, which is why your data gets appended. You need to open the file in read/write mode, seek() to the appropriate offset, and then write the replacement. Beware that the replacement must be exactly the same length as the original.
Given a file with contents thus:
15
20
25
This code will replace the 20 with 94:
use Fcntl qw(:seek);
open(my $fh, '+<', 'foo');
seek($fh, 3, SEEK_SET);
print $fh '94';
close($fh);
If you can't guarantee that the original and replacement text are the same length, then read the file, use an l-value substr() on the data, and write it back out again. The example below replaces the two characters at position three in the string with *three* characters. Obviously you'll need to handle opening, reading and writing the file yourself, but that's trivial:
$foo = "ab cd ef";
substr($foo, 3, 2) = "cat";
say $foo;