Isso pode ser feito apenas com a substituição de parâmetros do shell:
# setup
line='hello&xyz!60!world'
string='&xyz!'
variable2='!'
# now, remove from the beginning up to the first instance of "&xyz!"
tmp=${line#*$string}
# $tmp now holds 60!world
# remove from the end the last "!" and all following characters
result=${tmp%$variable2*}
echo $result
# => 60
Parece que seu comando sed está falhando devido à vírgula
-
sem vírgula na entrada, então nada corresponde, portanto nada é impresso
$ set -x $ echo "$line" | sed -nr "s/$string([0-9]+),$variable2// p" + sed -nr 's/&xyz!([0-9]+),!// p' + echo 'hello&xyz!60!world'
-
remova a vírgula, agora temos uma correspondência, mas o prefixo e o sufixo permanecem
$ echo "$line" | sed -nr "s/$string([0-9]+)$variable2// p" + sed -nr 's/&xyz!([0-9]+)!// p' + echo 'hello&xyz!60!world' hello60world
-
também corresponde ao texto anterior e posterior
$ echo "$line" | sed -nr "s/.*$string([0-9]+)$variable2.*// p" + sed -nr 's/.*&xyz!([0-9]+)!.*// p' + echo 'hello&xyz!60!world' 60