Eu fiz isso de duas maneiras, embora eu ache que eu gosto disso:
: $(( afterl=( lastl=$(wc -l <~/file) ) - 2 -
$(( beforel=( matchl=$(sed -n "/$IP/{=;q;}" <~/file) ) - 1
)) ))
for n in last match afters befores
do printf '%s line%s :\t%d\n' \
"${n%s}" "${n##*[!s]}" $((${n%s}l))
done
Isso salva todas as variáveis atuais do shell - e as avalia no loop for depois para a saída. Ele conta o total de linhas no arquivo com wc
e obtém o primeiro número de linha correspondente com sed
.
Sua saída:
last line : 1000
match line : 200
after lines : 799
before lines : 199
Eu também fiz:
sed -n "/$IP/=;\$=" ~/file |
tr \n \ | {
IFS=' ' read ml ll
printf '%s line%s:\t%d\n' \
last '' $((ll=${ll##* }))
match '' $ml \
after s "$((al=ll-ml-1)) \
before s $((bl=ml-1))
}
sed
imprime apenas números de correspondência e de última linha, em seguida, tr
traduz o% coexistente de ewlines para e \n
lê o primeiro dos resultados de read
em sed
e todos os outros em $ml
. Possíveis casos de múltiplas correspondências são tratados removendo todos, exceto o último resultado, da expansão de $ll
ao configurá-lo novamente mais tarde.
Sua saída:
last line : 1000
match line : 200
after lines : 799
before lines : 199
Ambos os métodos foram testados no arquivo gerado da seguinte maneira:
IP='some string for which I seek'
for count in 1 2 3 4 5
do printf '%.199d%s\n' 0 "$IP"
done | tr 0 \n >~/file
Por número de linha:
- define a string de pesquisa
- faz um loop cinco vezes para garantir que haverá várias correspondências
- imprime 199 zeros e, em seguida,
$ll
, em seguida, um "$IP"
ewline
- saída de tubos para
\n
- que converte zeros em tr
ewlines em seguida em \n