sed não é a ferramenta certa para o trabalho. No entanto, provavelmente ainda podemos fazer isso em sed :
sed -n '/^ 1 .* 2 .* 3$/,/^ 5$/ { /^ 1 .* 2 .* 3$/ { h }; /^ 4$/ { x; s/.*//; x;}; /^ 5$/ { x; p; x} }' filename | grep -v -e '^$'
Aqui está apenas a parte que adicionei ao seu bloco de intervalo:
/^ 1 .* 2 .* 3$/ { h }; /^ 4$/ { x; s/.*//; x;}; /^ 5$/ { x; p; x}
Leia isto como:
se a linha corresponder a regex /^ 1 .* 2 .* 3$/ e, em seguida, h (armazenar linha no buffer de retenção)
Se a linha corresponder a regex /^ 4$/ , então x (buffer de troca, ou seja, fazer operações se aplicam a armazenar buffer em vez de buffer padrão), substitua tudo em buffer de retenção * e x novamente (para voltar ao buffer padrão)
Se a linha corresponder a ^ 5$/ , mude para o buffer de retenção, p (imprima o conteúdo do buffer de retenção) e volte para o buffer padrão
* Infelizmente, s/.*// não exclui linhas no buffer de espera. A exclusão de linhas no buffer de retenção parece difícil, então nos livramos delas, canalizando para o grep -v -e '^$' .
Atualizar
Esta versão imprime o nome do arquivo após a correspondência (usando o comando F ) e gerencia sem canalizar para grep . Obrigado Paulo!
sed -n '/^ 1 .* 2 .* 3$/,/^ 5$/ { /^ 1 .* 2 .* 3$/ { h }; /^ 4$/ { x; s/.*//; x;}; /^ 5$/ { x; /^$/ !{ p; F }; x} }' data