O .* é ganancioso primeiro - corresponde a foo 6 . O único motivo para que ele pare é porque a correspondência de qualquer outra opção impediria a correspondência do padrão inteiro, deixando assim o 5 para o ([0-9]+) . Se você fizesse ([0-9]*) , em vez disso, o .* corresponderia à linha inteira e você não receberia nada no seu grupo. Uma maneira de contornar isso é dizer à primeira parte para não corresponder aos números:
$ echo "foo 65 bar" | sed -n -e 's/[^0-9]*\([0-9]\+\).*//p'
65