Você sempre pode fazer:
tac < fileName | sed '/EndPattern/,$!d;/StartPattern/q' | tac
Se o seu sistema não tiver o GNU tac
, você poderá usar tail -r
.
Você também pode fazer como:
awk '
inside {
text = text $0 RS
if (/EndPattern/) inside=0
next
}
/StartPattern/ {
inside = 1
text = $0 RS
}
END {printf "%s", text}' < filename
Mas isso significa ler todo o arquivo.
Observe que pode haver resultados diferentes se houver outro StartPattern
entre um StartPattern
e o próximo EndPattern
ou se o último StartPattern
não tiver um final EndPattern
ou se houver linhas correspondentes aos dois StartPattern
e EndPattern
.
awk '
/StartPattern/ {
inside = 1
text = ""
}
inside {text = text $0 RS}
/EndPattern/ {inside = 0}
END {printf "%s", text}' < filename
Faria isso se comportar mais como a abordagem tac+sed+tac
(exceto pelo caso não divulgado StartPattern
).
Esse último parece ser o mais próximo dos seus requisitos editados. Para adicionar o aviso seria simplesmente:
awk '
/StartPattern/ {
inside = 1
text = ""
}
inside {text = text $0 RS}
/EndPattern/ {inside = 0}
END {
printf "%s", text
if (inside)
print "Warning: EOF reached without seeing the end pattern" > "/dev/stderr"
}' < filename
Para evitar a leitura do arquivo inteiro:
tac < filename | awk '
/StartPattern/ {
printf "%s", $0 RS text
if (!inside)
print "Warning: EOF reached without seeing the end pattern" > "/dev/stderr"
exit
}
/EndPattern/ {inside = 1; text = ""}
{text = $0 RS text}'
Nota de portabilidade: para /dev/stderr
, você precisa de um sistema com um arquivo especial (cuidado com o Linux se o stderr estiver aberto em um arquivo pesquisável que gravará o texto no início do arquivo em vez da posição atual dentro do arquivo) ou uma implementação de awk
que o emula como gawk
, mawk
ou busybox awk
(os trabalhos em torno do problema do Linux mencionado acima).
Em outros sistemas, você pode substituir print ... > "/dev/stderr"
por print ... | "cat>&2"
.