Grep colorido - visualizando o arquivo inteiro com correspondências destacadas


509

Acho grepa --color=alwaysbandeira de ser tremendamente útil. No entanto, o grep imprime apenas linhas com correspondências (a menos que você solicite linhas de contexto). Dado que cada linha impressa tem uma correspondência, o realce não adiciona a maior capacidade possível.

Eu realmente gostaria de catum arquivo e ver o arquivo inteiro com as correspondências de padrões destacadas.

Existe alguma maneira de dizer ao grep para imprimir todas as linhas que estão sendo lidas, independentemente de haver uma correspondência? Eu sei que poderia escrever um script para executar o grep em todas as linhas de um arquivo, mas fiquei curioso para saber se isso era possível com o padrão grep.


1
se você quiser mais de uma cor para mais de um padrão (por exemplo, mensagens de erro, aviso, informações etc.), usesed . a sedsolução oferece várias cores ao custo de maior complexidade (em vez de cerca de 30 caracteres, você tem cerca de 60 caracteres).
Trevor Boyd Smith

Com o sed, você pode até destacar + retornar o código de saída , veja o exemplo: askubuntu.com/a/1200851/670392
Noam Manos

Respostas:


797

Aqui estão algumas maneiras de fazer isso:

grep --color -E 'pattern|$' file
grep --color 'pattern\|$' file
egrep --color 'pattern|$' file

152
Esse truque | $ é legal! Muito bem, vou ter que lembrar disso. Para aqueles que não são conhecedores de expressões regulares, "pattern | $" corresponderá às linhas que têm o padrão que você está procurando e as linhas que têm um fim - ou seja, todas elas. Como o final de uma linha não possui caracteres, a parte colorida da saída será apenas o seu padrão. Obrigado Ryan!
21413 zslayton

55
Você também pode omitir o "$": egrep --color "pattern|" file(credit stackoverflow.com/a/7398092/50979 )
13ren

15
@Zack, o "|" operador é um operador OR, não um E,
JBoy

16
@JBoy, eu estava usando 'AND' da maneira convencional em inglês, e não da maneira lógica booleana. Você está correto, é realmente um operador 'ou' - combina isso e aquilo. : P Bom esclarecimento.
zslayton

12
Parece que o "$" é necessário se corresponder a mais de um padrão. egrep --color "pattern1|pattern2|$". Caso contrário, o realce da cor não ocorrerá.
precisa saber é o seguinte

91

Aqui está algo na mesma linha. As chances são de que você usará menos de qualquer maneira, então tente o seguinte:

less -p pattern file

Ele destacará o padrão e pulará para a primeira ocorrência dele no arquivo.


4
Também funciona com tubulação (leitura de stding) usando -:… | less -p pattern -
phk

3
@phk: Você pode até omitir o traço.
Pausado até novo aviso.

Além disso, adicionar a -iopção fará com que a correspondência não seja diferenciada como em less -ip pattern file.
steveb

... e se a tubulação estiver na entrada colorida ANSI, forneça lesso -Rcomutador:… | less -Rip introduction -
Abdull

48

Eu gostaria de recomendar o ack - melhor que o grep, uma ferramenta de busca avançada para programadores .

$ ack --color --passthru --pager = "$ {PAGER: -less -R}" arquivos padrão
$ ack --color --passthru arquivos padrão | menos -R
$ export ACK_PAGER_COLOR = "$ {PAGER: -less -R}"
Arquivos de padrão $ ack --passthru

Eu amo isso porque o padrão é a pesquisa recursiva de diretórios (e é muito mais inteligente do que grep -r), suporta expressões regulares completas do Perl (em vez do POSIXish regex(3)) e possui uma exibição de contexto muito mais agradável ao pesquisar muitos arquivos.


2
No entanto, de tempos em tempos, ele não encontra o que quero quando tenho certeza de que deve estar lá. acké inteligente, mas às vezes muito inteligente, e EXCLUÍDA o tipo de arquivo que o hit estava.
Michael Piefel

4
@MPi ack -airá procurar todos os tipos de arquivos, enquanto ainda excluindo .git/ .svn/etc.
ephemient

1
No entanto, é legal que acknão procure nas minhas imagens, o que -afaz muito. Eu adicionei --type-set=freemarker=.ftlao meu ~/.ackrc, para dar um exemplo.
22612 Michael Piefel

3
Com alguns ajustes na configuração, o grep já faz tudo que o ack faz, é mais rápido e nunca omite resultados, como as listas de permissões do ack às vezes fazem. Talvez salve suas configurações preferidas de grep em .bashrc. Mina lê: função GRP () {GREP_OPTIONS = - grep "$ @" "ri --color --exclude-dir = \ git --exclude = tags."
Jonathan Hartley

22

Você pode usar meu highlightscript em https://github.com/kepkin/dev-shell-essentials

É melhor do que grepporque você pode destacar cada partida com sua própria cor .

$ command_here | highlight green "input" | highlight red "output"

Captura de tela do projeto Github


3
A pergunta solicitou expressamente uma solução usando grep, que é um utilitário padrão em máquinas executando * nix.
precisa saber é o seguinte

1
Este script é bom, mas não tão bom quanto coloutmencionado em outra resposta.
Jonathan Hartley

@ JonathanHartley E por que isso acontece? Não vejo razão para isso. Além disso, este script usa uma implementação muito mais simples do que colout, o que é bom se você quiser inspecionar o que faz.
HelloGoodbye 10/01/19

@HelloGoodbye Sim, é justo. Eu deveria adiar o julgamento. O colout é mais completo e poderoso, mas você está certo de que é correspondentemente mais complexo de usar e fazer engenharia reversa.
Jonathan Hartley

@JonathanHartley Faz sentido que seja mais poderoso!
HelloGoodbye 15/01/19

19

Você também pode criar um alias. Adicione esta função ao seu .bashrc (ou .bash_profile no osx)

function grepe {
    grep --color -E "$1|$" $2
}

Agora você pode usar o alias assim: " ifconfig | grepe inet" ou " grepe css index.html".

(PS: não esqueça source ~/.bashrcde recarregar o bashrc na sessão atual)


você também pode usar o egrep, se estiver disponível no seu sistema.
Tom

1
A tubulação do resultado disso perde menos as informações de cores. Como você impediria isso?
Connor Clark

5
@Hoten use em --color=alwaysvez de--color
limp_chimp 4/16

3
E, para lessinterpretar os códigos de cores, use less -R.
Eliah Kagan

O uso não cotado de US $ 2 não está em branco. Em um bash, eu prefiro executar a função grepe () {local pattern = "$ 1" shift egrep --color "$ pattern | ^" "$ @"} Desculpe a bagunça na formatação.
21818 Robert Klemme

16

Use o coloutprograma: http://nojhan.github.io/colout/

Ele foi projetado para adicionar realces de cores a um fluxo de texto. Dada uma expressão regular e uma cor (por exemplo, "vermelho"), ele reproduz um fluxo de texto com as correspondências destacadas. por exemplo:

# cat logfile but highlight instances of 'ERROR' in red
colout ERROR red <logfile

Você pode encadear várias invocações para adicionar vários destaques de cores diferentes:

tail -f /var/log/nginx/access.log | \
    colout ' 5\d\d ' red | \
    colout ' 4\d\d ' yellow | \
    colout ' 3\d\d ' cyan | \
    colout ' 2\d\d ' green

Ou você pode conseguir o mesmo usando uma regex com N grupos (partes entre parênteses da regex), seguida por uma lista separada por vírgula de N cores.

vagrant status | \
    colout \
        '\''(^.+  running)|(^.+suspended)|(^.+not running)'\'' \
        green,yellow,red

1
Como observado em outro lugar, a pergunta solicitou expressamente uma solução usando grep, que é um utilitário padrão em máquinas executando * nix.
zslayton

4
@ Zack ok, desculpe. Na verdade, se você expandir o problema além grep, e ele já estiver expandido nas respostas, colouté a melhor solução para o problema que você teve, a melhor que eu conheço. De acordo com a filosofia do UNIX, os programas devem ser escritos para fazer uma coisa bem. Pois grepé filtrar o fluxo de texto. Pois colouté colorir ou destacar o fluxo de texto.
user2683246

Essa é a melhor resposta, pois pode aplicar vários destaques coloridos diferentes e colouté uma ferramenta muito útil. Aprendê-lo uma vez, usá-lo em muitas situações, em vez de aprender uma ferramenta para arquivos de log destaque, outra saída de teste para destaque, etc.
Jonathan Hartley

9

Eu uso o rcg do "Linux Server Hacks", O'Reilly. É perfeito para o que você deseja e pode destacar várias expressões, cada uma com cores diferentes.

#!/usr/bin/perl -w
#
#       regexp coloured glasses - from Linux Server Hacks from O'Reilly
#
#       eg .rcg "fatal" "BOLD . YELLOW . ON_WHITE"  /var/adm/messages
#
use strict;
use Term::ANSIColor qw(:constants);

my %target = ( );

while (my $arg = shift) {
        my $clr = shift;

        if (($arg =~ /^-/) | !$clr) {
                print "Usage: rcg [regex] [color] [regex] [color] ...\n";
                exit(2);
        }

        #
        # Ugly, lazy, pathetic hack here. [Unquote]
        #
        $target{$arg} = eval($clr);

}

my $rst = RESET;

while(<>) {
        foreach my $x (keys(%target)) {
                s/($x)/$target{$x}$1$rst/g;
        }
        print
}

7

A -zopção para grep também é muito boa!

cat file1 | grep -z "pattern"

o que isso faz? -z diz ao grep para usar ASCII NUL como um delimitador de linha ...
vy32 31/12/19

6

Adicionei isso ao meu .bash_aliases:

highlight() {
  grep --color -E "$1|\$"
}

3

Para destacar padrões enquanto visualiza o arquivo inteiro, h pode fazer isso.

Além disso, ele usa cores diferentes para diferentes padrões.

cat FILE | h 'PAT1' 'PAT2' ...

Você também pode canalizar a saída de hpara less -Rpara uma melhor leitura.

Para grep e usar 1 cor para cada padrão, o cxpgrep pode ser um bom ajuste.


1

Ok, este é um caminho,

wc -l filename

lhe dará a contagem de linhas - diga NN, então você pode fazer

grep -C NN --color=always filename

3
"-C 2147483647" se você não quiser primeiro wc. Usar um número grande aqui não parece desacelerar as coisas.
precisa saber é o seguinte

1

Aqui está um script de shell que usa a função gsub do Awk para substituir o texto que você está procurando pela seqüência de escape adequada para exibi-lo em vermelho brilhante:

#! /bin/bash
awk -vstr=$1 'BEGIN{repltext=sprintf("%c[1;31;40m&%c[0m", 0x1B,0x1B);}{gsub(str,repltext); print}' $2

Use-o assim:

$ ./cgrep pattern [file]

Infelizmente, ele não tem toda a funcionalidade do grep.

Para obter mais informações, consulte o artigo " So You Like Color " no Linux Journal.


1

Uma outra resposta mencionou a opção -Cn do grep, que inclui n linhas de contexto. Às vezes, faço isso com n = 99 como uma maneira rápida e suja de obter [pelo menos] uma tela cheia de contexto quando o padrão egrep parece muito complicado ou quando estou em uma máquina na qual não instalei o rcg e / ou ccze.

Eu descobri recentemente cczeque é um colorizador mais poderoso. Minha única reclamação é que ela é orientada à tela (tipo less, que eu nunca uso por esse motivo), a menos que você especifique a opção -A para a saída "bruto ANSI".

+1 para a rcgmenção acima. Ainda é o meu favorito, pois é muito simples de personalizar em um pseudônimo. Algo como isso geralmente está no meu ~ / .bashrc:

alias tailc = 'tail -f / meu / app / log / arquivo | rcg envia "BOLD GREEN" recebe o erro "CYAN" "RED" '


1

outra maneira suja:

grep -A80 -B80 --color FIND_THIS IN_FILE

Eu fiz um

alias grepa='grep -A80 -B80 --color'

no bashrc.


1
isso é problemático se as coisas que você procura não estão lá. Digamos que devido a um erro; nesse caso, você não receberá nada.
Paul Rubel 12/09


0

Se você deseja destacar vários padrões com cores diferentes, consulte este script bash.

Uso básico:

echo warn error debug info 10 nil | colog

Você pode alterar padrões e cores enquanto estiver executando, pressionando uma tecla e depois a tecla Enter.


0

Eu uso o seguinte comando para fins semelhantes:

grep -C 100 searchtext file

Isso indica grep para imprimir 100 * 2 linhas de contexto, antes e depois do texto de pesquisa destacado.


0

Aqui está minha abordagem , inspirada na solução do @ kepkin:

# Adds ANSI colors to matched terms, similar to grep --color but without
# filtering unmatched lines. Example:
#   noisy_command | highlight ERROR INFO
#
# Each argument is passed into sed as a matching pattern and matches are
# colored. Multiple arguments will use separate colors.
#
# Inspired by https://stackoverflow.com/a/25357856
highlight() {
  # color cycles from 0-5, (shifted 31-36), i.e. r,g,y,b,m,c
  local color=0 patterns=()
  for term in "$@"; do
    patterns+=("$(printf 's|%s|\e[%sm\\0\e[0m|g' "${term//|/\\|}" "$(( color+31 ))")")
    color=$(( (color+1) % 6 ))
  done
  sed -f <(printf '%s\n' "${patterns[@]}")
}

Isso aceita vários argumentos (mas não permite que você personalize as cores). Exemplo:

$ noisy_command | highlight ERROR WARN

-1

Existe alguma maneira de dizer ao grep para imprimir todas as linhas que estão sendo lidas, independentemente de haver uma correspondência?

Option -C999fará o truque na ausência de uma opção para exibir todas as linhas de contexto. A maioria das outras variantes do grep também suporta isso. Entretanto: 1) nenhuma saída é produzida quando nenhuma correspondência é encontrada e 2) essa opção tem um impacto negativo na eficiência do grep: quando o-C valor é grande, muitas linhas podem precisar ser temporariamente armazenadas na memória do grep para determinar quais linhas de contexto para exibir quando ocorrer uma correspondência. Observe que as implementações grep não carregam arquivos de entrada, mas lê algumas linhas ou usam uma janela deslizante sobre a entrada. A "parte anterior" do contexto deve ser mantida em uma janela (memória) para gerar as linhas de contexto "anterior" mais tarde, quando uma correspondência for encontrada.

Um padrão como ^|PATTERNou PATTERN|$ou qualquer sub-padrão de correspondência vazia, por exemplo, [^ -~]?|PATTERNé um bom truque. No entanto, 1) esses padrões não mostram linhas não correspondentes destacadas como contexto e 2) isso não pode ser usado em combinação com outras opções de grep, como -Fe -wpor exemplo.

Portanto, nenhuma dessas abordagens me satisfaz. Estou usando o ugrep e o grep aprimorado com a opção -yde exibir com eficiência todas as saídas não correspondentes como linhas de contexto destacadas em cores. Outras ferramentas do tipo grep, como ag e ripgrep, também oferecem uma opção de passagem. Mas o ugrep é compatível com o GNU / BSD grep e oferece um superconjunto de opções de grep como -ye -Q. Por exemplo, eis a opção -ymostrada quando combinada com -Q(UI de consulta interativa para inserir padrões):

ugrep -Q -y FILE ...

Por que votar isso sem deixar um comentário? É mais do que justo mencionar ferramentas alternativas de grep, assim como algumas das outras respostas.
Dr. Alex RE
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.