grep um arquivo, mas mostra várias linhas circundantes?

3420

Gostaria de grepobter uma string, mas também mostrar as cinco linhas anteriores e as cinco linhas seguintes, bem como a linha correspondente. Como eu seria capaz de fazer isso?

Mark Harrison
fonte
3
Eu mantenho uma cópia do script perl de Brendan Gregg para esse fim. Funciona bem.
Ethan Post
6
Para uma solução que funcione no Solaris, confira este link .
Jahroy 30/05
107
man grep | grep -C 1 context:)
StvnW
20
man grep | grep -C 1 "\-C";)
Anders B
9
@StvnW ... Não sei se devo chamar essa meta (em um contexto mais geral, e não SO), ou como chamá-la. Você respondeu à pergunta mostrando como usar a resposta para encontrar a resposta.
bballdave025

Respostas:

4539

Para BSD ou GNU, grep você pode usar -B numpara definir quantas linhas antes da partida e -A numo número de linhas após a partida.

grep -B 3 -A 2 foo README.txt

Se você deseja o mesmo número de linhas antes e depois da utilização -C num.

grep -C 3 foo README.txt

Isso mostrará 3 linhas antes e 3 linhas depois.

Pat Notz
fonte
56
É bom, mas infelizmente o Solaris grep não suporta isso. Veja esse link para o solaris: unix.com/solaris/33533-grep-display-few-lines-before-after.html #
21411
9
Ok, mas e se quiser mostrar todas as linhas de saída após a partida? O grep -A0 e o grep -A-1 não cortam ...
g33kz0r
2
não funciona para mim por algum motivo, embora mencionado nas minhas páginas de manual.
Hayri Uğur Koltuk
2
Se você é um servidor HP-UX, nenhuma das versões grep funcionará como no Solaris. Conseguiu usar o link Solaris, mas substituiu o nawk pelo awk nesse link.
Zkarthik
6
-n é para números de linha, mas para algumas versões do grep -n # mostrará # linhas circundantes (como -c) com números de linha. Esse é um atalho útil que é meu objetivo quando preciso de contexto.
Anthony DiSanti
607

-Ae -Bfuncionará como quiser -C n(para nlinhas de contexto) ou apenas -n(para nlinhas de contexto ... desde que n seja de 1 a 9).

Stu
fonte
Eu tentei o -nformato e descobri que só funciona até 9. Para 15isso, ele retorna 5 linhas
Deepak Mahakale 27/03/19
8
@DeepakMahakale Isso provavelmente está relacionado a como os argumentos / opções da linha de comando são normalmente analisados ​​pelos programas POSIX. O especificador de opção é um único caractere (como -A, -Bou -C). Geralmente, o especificador de opção é seguido por um valor ( -o a.outpara especificar o arquivo de saída no GCC), mas também pode funcionar como uma opção / sinalização simples ( -gpara ativar as informações de depuração no GCC). No entanto, os espaços entre as opções são opcionais; portanto, para opções sem valor, é possível mesclá-las ( -ABC), o que significa que -15é interpretado -1 -5(duas opções separadas) e as -5substituições são -1.
Natiiix 19/04/19
1
-5 é mais rápido que ambos -A 5 -B 5. Esses não devem ser usados ​​juntos. É mais limpo para outros leitores do script se você escolher -A ou -B ou -C acima de -9.
Eric Aldinger 07/07/19
77

O ack trabalha com argumentos semelhantes ao grep e aceita -C. Mas geralmente é melhor pesquisar no código.

elmarco
fonte
5
O ack também suporta -A -B.
Shuo
Ack é melhor que grep de várias maneiras. É mais rápido com uma sintaxe mais simples.
Chim
1
O grep tem a vantagem de ser instalado por padrão em muitos sistemas.
Marc Z
1
@ MarcZ: É verdade que é mais provável que o grep seja instalado por padrão do que o ack, mas o ack é um script portátil e independente. Não há necessidade de compilá-lo ou instalá-lo em um diretório do sistema como / usr / bin /. Depois de baixado e colocado em um diretório listado no $ PATH (e seu conjunto de bits de permissão eXecute), ele deve funcionar imediatamente. (Sem sudo ou raiz privilégios são necessários para obter ack ao trabalho.)
JL
Esta questão é sobre grep, não tenho certeza de que usá-lo para "anunciar" ack(que é uma ótima ferramenta, de fato) é uma boa idéia ...
MonsieurDart
39
grep astring myfile -A 5 -B 5

Isso grep "myfile" para "adstring", e mostra 5 linhas antes e depois de cada partida

dbr
fonte
19
"grep astring myfile -C 5" fará o mesmo
Syed Siraj Uddin
20

Eu normalmente uso

grep searchstring file -C n # n for number of lines of context up and down

Muitas das ferramentas, como o grep, também possuem arquivos man muito bons. Eu me pego me referindo muito à página de manual do grep porque há muito que você pode fazer com isso.

man grep

Muitas ferramentas GNU também têm uma página de informações que pode ter informações mais úteis além da página de manual.

info grep
Sam Merrell
fonte
13

Use grep

$ grep --help | grep -i context
Context control:
  -B, --before-context=NUM  print NUM lines of leading context
  -A, --after-context=NUM   print NUM lines of trailing context
  -C, --context=NUM         print NUM lines of output context
  -NUM                      same as --context=NUM
Chiel ten Brinke
fonte
Você não leu a resposta aceita? Você está apenas repetindo o que já foi dito sobre uma pergunta com quase 10 anos de idade ...
Yokai
7
Oh, desculpe Yokai. Mas não li nada sobre grepping na seção de ajuda do grep para recuperar a resposta.
Chiel ten Brinke
1
@Yokai Além do que Chiel ten Brinke disse, a resposta aceita não mencionar as opções longas
user3738870
11

Procure por "17655" em "/some/file.txt" mostrando o contexto de 10 linhas antes e depois (usando o Awk), saída precedida pelo número da linha seguido por dois pontos. Use isso no Solaris quando o 'grep' não suportar as opções "- [ACB]".

awk '

/17655/ {
        for (i = (b + 1) % 10; i != b; i = (i + 1) % 10) {
                print before[i]
        }
        print (NR ":" ($0))
        a = 10
}

a-- > 0 {
        print (NR ":" ($0))
}

{
        before[b] = (NR ":" ($0))
        b = (b + 1) % 10
}' /some/file.txt;
Malcolm Boekhoff
fonte
7

ripgrep

Se você se preocupa com o desempenho, use ripgrepuma sintaxe semelhante a grep, por exemplo,

rg -C5 "pattern" .

-C, --context NUM- Mostrar NUM linhas antes e depois de cada partida.

Também existem parâmetros como -A/ --after-contexte -B/--before-context .

A ferramenta é construída sobre o mecanismo regex da Rust, o que a torna muito eficiente em grandes dados.

kenorb
fonte
5

Aqui está a solução @Ygor emawk

awk 'c-->0;$0~s{if(b)for(c=b+1;c>1;c--)print r[(NR-c+1)%b];print;c=a}b{r[NR%b]=$0}' b=3 a=3 s="pattern" myfile

Nota: Substitua aeb variáveis ​​pelo número de linhas antes e depois.

É especialmente útil para o sistema que não suporta o grep -A, -Be -Cparâmetros.

kenorb
fonte
4
$ grep thestring thefile -5

-5coloca as 5linhas acima e abaixo da correspondência 'thestring' é equivalente a -C 5ou -A 5 -B 5.

JBone
fonte
4

O Grep tem uma opção chamada Context Line Control, você pode usar o --contextque, simplesmente,

| grep -C 5

ou

| grep -5

Deve fazer o truque

prime
fonte
1

Eu costumo fazer da maneira compacta

grep -5 string file

Isso é o equivalente a

grep -A 5 -B 5 string file
franzisk
fonte
0

Se você pesquisar código com frequência, AG , o pesquisador prateado é muito mais eficiente (ou seja, mais rápido) do que o grep.

Você mostra as linhas de contexto usando a opção -C.

Por exemplo:

ag -C 3 "foo" myFile

line 1
line 2
line 3
line that has "foo"
line 5
line 6
line 7
Rosa
fonte