Eu tenho que grep através de alguns arquivos JSON nos quais os comprimentos de linha excedem alguns milhares de caracteres. Como posso limitar o grep para exibir o contexto de até N caracteres à esquerda e à direita da partida? Qualquer ferramenta que não seja grep também ficaria bem, desde que disponível em pacotes Linux comuns.
Isso seria exemplo de saída, para o switch grep imaginário Ф :
$ grep -r foo *
hello.txt: Once upon a time a big foo came out of the woods.
$ grep -Ф 10 -r foo *
hello.txt: ime a big foo came of t
Respostas:
Com o GNU
grep
:Explicação:
-o
=> Imprima apenas o que você combinou-P
=> Use expressões regulares no estilo Perl$N
caracteresfoo
seguido por 0 aos$N
caracteres.Se você não possui GNU
grep
:Explicação:
Como não podemos mais confiar em
grep
ser o GNUgrep
, utilizamosfind
para procurar arquivos recursivamente (a-r
ação do GNUgrep
). Para cada arquivo encontrado, executamos o snippet Perl.Comutadores Perl:
-n
Leia o arquivo linha por linha-l
Remova a nova linha no final de cada linha e coloque-a novamente ao imprimir-e
Trate a seguinte string como códigoO snippet Perl está fazendo essencialmente a mesma coisa que
grep
. Começa definindo uma variável$N
para o número de caracteres de contexto que você deseja. OsBEGIN{}
meios que isso é executado apenas uma vez no início da execução, não uma vez para cada linha em cada arquivo.A instrução executada para cada linha é imprimir a linha se a substituição de regex funcionar.
A regex:
^.*?
) seguida por,.{0,$N}
como nogrep
caso,foo
seguido de outra.{0,$N}
e, finalmente, faça a correspondência de qualquer coisa antiga preguiçosamente até o final da linha (.*?$
).$ARGV:$1
.$ARGV
é uma variável mágica que contém o nome do arquivo atual que está sendo lido.$1
é o que os parênteses combinavam: o contexto neste caso.foo
sem deixar de corresponder (já que.{0,$N}
é permitido corresponder zero vezes).1 Ou seja, prefira não corresponder a nada, a menos que isso cause uma falha na correspondência geral. Em resumo, combine o mínimo de caracteres possível.
fonte
| grep foo
ao final (no entanto, perdendo o destaque do nome do arquivo no processo).grep
você pode especificar cores / aplicativos correspondentes com base em sinalizadores aplicados por variáveis de ambiente. então talvez você possa ganhar todos eles (sem promessas - nem mesmo certo se funcionaria nesse caso), mas eu pessoalmente não vejo a relevância aqui ... de qualquer maneira ... continue jogando.zsh
eu sou incapaz de fazê-lo passar N = 10, como no exemplo. No entanto, ele funciona se euexport N=10
antes de executar o comando. Alguma idéia de como ajustar o exemplo para trabalhar com o zsh?perl -lne 'print "$ARGV: $_" for /.{0,10}foo.{0,10}/g'
Tente usar este:
-E diz que você deseja usar regex estendido
-o informa que você deseja imprimir apenas a correspondência
-r grep está procurando resultado recursivamente na pasta
REGEX:
{0,10} informa quantos caracteres arbitrários você deseja imprimir
. representa um personagem arbitrário (um personagem em si não era importante aqui, apenas seu número)
Edit: Ah, entendo, que Joseph recomenda quase a mesma solução que eu: D
fonte
-E
é significativamente mais rápido que-P
.Retirado de: http://www.topbug.net/blog/2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preserves-color/ e https: // stackoverflow. com / a / 39029954/1150462
A abordagem sugerida
".{0,10}<original pattern>.{0,10}"
é perfeitamente boa, exceto pelo fato de que a cor de destaque é muitas vezes confusa. Eu criei um script com uma saída semelhante, mas a cor também é preservada:Supondo que o script seja salvo como
grepl
,grepl pattern file_with_long_lines
deve exibir as linhas correspondentes, mas com apenas 10 caracteres ao redor da sequência correspondente.fonte
Tubulação stdout para
cut
com a-b
bandeira; você pode instruir a saída do grep apenas para bytes 1 a 400 por linha.fonte