Talvez algo como:
sed 'H;/#$/!d;s/^/\
/;x;/\n%/!d;s/.//;x;s/.*//;x'
Como você deseja o prompt antes do erro e após o erro, esse inclui os dois, exceto os prompts que, caso contrário, apareceriam como o prompt após um erro e o anterior ao próximo erro para corresponder à saída de amostra.
É muito mais simples incluir os dois prompts, independentemente de os erros se seguirem ou não:
sed 'H;/#$/!d;x;/\n%/!d'
Se você quisesse apenas o prompt antes do erro, isso também seria muito mais simples:
sed '/#$/!{H;d;}
x;/\n%/!d'
Provavelmente, a melhor maneira de explicar isso é traduzir para uma linguagem mais detalhada como perl
. Em sed
, o espaço de espera é como uma variável estática que é inicializada com uma linha vazia e o espaço de padrão é uma variável que sed
atribui, por sua vez, a cada linha de entrada. Algo como:
$hold_space = "\n";
LINE: while ($pattern_space = <>) {
<sed commands go here>
print $pattern_space; # unless -n option is passed
}
O comando H
é traduzido para:
$hold_space .= $pattern_space;
O comando d
é traduzido para:
next LINE;
Isso é parar de executar os comandos, descartar o espaço padrão e começar de novo com a próxima linha de entrada.
x
troca o padrão e armazena o espaço:
($pattern_space, $hold_space) = ($hold_space, $pattern_space);
Para que o último comando sed
seja traduzido para:
$hold_space = "\n";
LINE: while ($pattern_space = <>) {
if (! ($pattern_space =~ /#$/)) { # anything other than a prompt
$hold_space .= $pattern_space;
next LINE;
}
($pattern_space, $hold_space) = ($hold_space, $pattern_space);
if (! ($pattern_space =~ /\n%/)) {
next LINE;
}
print $pattern_space;
}
Que pode ser reescrito de uma forma mais legível como:
LINE: while ($pattern_space = <>) {
if ($pattern_space =~ /#$/)) {
if ($hold_space =~ /\n%/)) {
print $hold_space;
}
$hold_space = $pattern_space;
} else {
$hold_space .= $pattern_space;
}
}
Renomeie $pattern_space
para $line
e $hold_space
para $current_block
e fique ainda mais legível.