With perl, finding all sequences of decimal digits and rounding them up to multiple of 4096:
$ echo foo123bar 4095-4097 1e+4 0x1f2 004123 3.4 |
perl -pe 's{\d+}{int(($& + 4095)/4096)*4096}ge'
foo4096bar 4096-8192 4096e+4096 0x4096f4096 8192 4096.4096
$ echo 'foo123bar 4095-4097 1e+4 0x1f2 004123 3.4' |
perl -pe 's{\d+}{int(($& + 4095)/4096)*4096}ge'
foo4096bar 4096-8192 4096e+4096 0x4096f4096 8192 4096.4096
If you wanted to consider those -4097, 1e+4, 0x1f2, 3.4 as the negative / floating point / hexadecimal numbers they represent instead of only considering the sequences of decimal digits within, you could change it to:
$ echo 0x1p13 foo123bar 4095-4097 4096.001 1e+4 0x1f2 004123 3.4 infinity nan |
perl -MPOSIX=floor,strtold -pe '
s{0x[\da-f]+(p[-+]?\d+)?|[-+]?(\d+\.?\d*|\.\d+)(e[-+]?\d+)?|\b(inf(inity)?|nan)\b}{
($x) = strtold($&);
$y = floor($x / 4096) * 4096;
$y == $x ? $y : $y+4096
}gie'
8192 foo4096bar 4096-4096 8192 12288 4096 8192 4096 Inf NaN
$ echo '0x1p13 foo123bar 4095-4097 4096.001 1e+4 0x1f2 004123 3.4 infinity nan' |
perl -MPOSIX=floor,strtold -pe '
s{0x[\da-f]+(p[-+]?\d+)?|[-+]?(\d+\.?\d*|\.\d+)(e[-+]?\d+)?|\b(inf(inity)?|nan)\b}{
($x) = strtold($&);
$y = floor($x / 4096) * 4096;
$y == $x ? $y : $y+4096
}gie'
8192 foo4096bar 4096-4096 8192 12288 4096 8192 4096 Inf NaN
Change ? $y to ? $& to not reformat the numbers that are multiples of 4096 as decimal integer (as in keep for instance 0x1000, 0X1P12, +40.96E+2, 4096.000 as is and not change them to 4096).