Portably:
sed '
s/.*/ & /; # add a leading and trailing space
:1
s/\([[:blank:]]541[^[:blank:]]\{2\}\)\([^[:blank:]]\{5\}[[:blank:]]\)/\19\2/g
# replace in a loop until there is no more match
t1
# remove the blanks we added earlier:
s/^ //;s/ $//'
You can avoid the temporary adding of the leading and trailing spaces by looking for the occurrence of that 10 non-blank string at the beginning or the end of the list in addition to following/preceding a blank. That can be done POSIXly with one regexp, but that's a bit unwieldy:
sed '
:1
s/^\(\(.*[[:blank:]]\)\{0,1\}541[^[:blank:]]\{2\}\)\([^[:blank:]]\{5\}\([[:blank:]].*\)\{0,1\}\)$/\19\3/
t1'
With `perl`, using look-around operators:
perl -lpe 's/((?<!\H)541\H\H)(\H{5})(?!\H)/${1}9$2/g'
Or processing words one by-one:
perl -lpe 's{\H+}{$&=~s/^541..\K.{5}$/9$&/r}ge'
(`\K` and the `r` substitution flag require a relatively recent version of `perl`).