Você pode fazer isso com a opção grep
-B
( --before-context
):
grep -B 20 error filename
Atualmente:
Eu sou novo em escrever, ensinando a mim mesmo enquanto eu vou e este é o meu primeiro script que estou desenvolvendo. O que meu script está tentando fazer é olhar para o arquivo especificado, digitalizar o arquivo para encontrar a palavra "Erro". Atualmente, ele imprime o restante do arquivo do ponto "ERROR" em um arquivo de saída.
Problema:
Depois de encontrar a palavra "ERRO" em um arquivo, como posso imprimir as 20 linhas anteriores do texto da palavra "ERROR" para um arquivo de saída e acrescentar o resto do arquivo do ponto "ERROR" para o mesmo arquivo de saída?
Solução possível?
Eu usaria algum tipo de loop aqui para fazer isso? Eu tenho o código sudo = na minha cabeça como fazer isso pode funcionar, mas não sei como realmente implementar isso. Alguém pode me aconselhar ou me dizer se existe uma maneira melhor de fazer isso?
Script:
my $file_handle = IO::File->new ('output','a') or die;
print $file_handle "*****************************\n";
while(<>) {
print $file_handle $_ if(/.*ERROR/ .. /^XXX/);
}
Você pode fazer isso com a opção grep
-B
( --before-context
):
grep -B 20 error filename
awk: Estou apenas mantendo 5 linhas para esta demonstração, ajuste o valor "keep" para 20
{ seq 10; echo ERROR; seq 6; } |
awk -v keep=5 '
/ERROR/ {
for (i=keep; i>=1; i--) print lines[i] # the stored lines
print # the current line
while (getline > 0) print # all the remaining lines
}
{
# remember the previous "keep" lines.
for (i=keep; i>1; i--)
lines[i] = lines[i-1]
lines[1] = $0
}
'
6
7
8
9
10
ERROR
1
2
3
4
5
6
Outra abordagem: leva 2 leituras pelo arquivo, mas é mais claro, eu acho.
keep=20
lineno=$(sed -n '/ERROR/{=;q;}' file)
[[ -n $lineno ]] && sed -n "$((lineno-keep)),\$p" file
Se eu estivesse fazendo isso no bash, faria algo assim:
line=$(grep -m1 -n ERROR the_file | cut -f1 -d:)
if ((line <= 20)); then
cat the_file;
else
tail -n+$((line-20)) the_file
fi
que usa grep
com a opção "mostrar números de linha" · para obter o número da linha da partida e tail -n
para imprimir a partida com a 20ª linha anterior, evitando um número de linha inicial negativo .
Em qualquer outro idioma, a solução seria manter um buffer contínuo (talvez circular) das últimas 20 linhas lidas. Por exemplo, no awk, com um buffer circular:
awk -v P=20 'found { print; next }
/ERROR/{ for (i=NR+1;i<=NR+P;++i)
if (i%P in saved)
print saved[i%P]
found = 1
}
{ saved[NR%P] = $0 }'
Tags bash shell-script