Convença o grep a produzir todas as linhas, não apenas aquelas com correspondências

120

Digamos que eu tenha o seguinte arquivo:

$ cat test

test line 1
test line 2
line without the search word
another line without it
test line 3 with two test words
test line 4

Por padrão, grep retorna cada linha que contém o termo de pesquisa:

$ grep test test

test line 1
test line 2
test line 3 with two test words
test line 4

Passar o parâmetro --color para grep fará com que ele realce a parte da linha que corresponde à expressão de pesquisa, mas ainda retorna apenas linhas que contenham a expressão. Existe uma maneira de obter grep para gerar todas as linhas no arquivo de origem, mas destacar as correspondências?

Meu truque terrível atual para realizar isso (pelo menos em arquivos que não têm mais de 10000 linhas consecutivas sem correspondência) é:

$ grep -B 9999 -A 9999 test test

Segrepnãoconseguirisso,existeoutraferramentadelinhadecomandoqueofereceamesmafuncionalidade?Eumexiem ack , mas também não parece ter uma opção para isso.

    
por Michael Mrozek 12.08.2010 / 04:39

11 respostas

180
grep --color -E "test|$" yourfile

O que estamos fazendo aqui é comparar com o padrão $ e o padrão de teste, obviamente $ não tem nada para colorir, então apenas o padrão de teste fica colorido. O -E apenas ativa a correspondência estendida de expressão regular.

Você pode criar uma função com facilidade assim:

highlight () { grep --color -E "$1|$" "${@:1}" ; }
    
por 12.08.2010 / 04:52
39
ack --passthru --color string file

para Ubuntu e Debian, use ack-grep em vez de ack

ack-grep --passthru --color string file
    
por 17.08.2010 / 21:59
12

Outra maneira de fazer isso corretamente e portavelmente com grep (além de usar duas regexes com alternância como na resposta aceita) é por meio do padrão nulo (e respectivamente string nula).
Ele deve funcionar igualmente bem com as opções -E e -F desde então, conforme o padrão :

-E
    Match using extended regular expressions. 
    [...] A null ERE shall match every line.

e

-F
    Match using fixed strings.
    [...] A null string shall match every line.

Portanto, é simplesmente uma questão de executar

grep -E -e '' -e 'pattern' infile

e respectivamente

grep -F -e '' -e 'string' infile
    
por 26.01.2017 / 23:54
11

Eu tenho a seguinte função que uso para essas coisas:

highlight () {
    perl -pe "s/$1/\e[1;31;43m$&\e[0m/g"
}

Internamente parece meio feio, é legal e fácil de usar, assim:

cat some_file.txt | highlight some_word

ou, para um exemplo um pouco mais real:

tail -f console.log | highlight ERROR

Você pode alterar as cores para qualquer coisa que quiser (o que pode ser difícil com o grep - não tenho certeza) alterando os 1 e 31 e 43 (após \e[ ) para valores diferentes . Os códigos a usar são tudo sobre o local , mas aqui está uma introdução rápida: o 1 negrita o texto, o 31 torna vermelho e o 43 fornece um fundo amarelo. 32 ou 33 seriam cores diferentes e 44 ou 45 seriam origens diferentes: você entendeu. Você pode até fazê-lo piscar (com 5 ) se você estiver inclinado.

Isso não usa módulos Perl especiais, e o Perl é quase onipresente, então eu esperaria que funcionasse praticamente em qualquer lugar. A solução grep é muito inteligente, mas a opção --color no grep não está disponível em todos os lugares. Por exemplo, eu apenas tentei esta solução em uma caixa do Solaris rodando o bash, e outro executando o ksh, e minha máquina local do Mac OS X rodando o zsh. Tudo funcionou muito bem. Solaris bloqueado na solução grep --color , no entanto.

Além disso, o ack é incrível, e eu o recomendo para quem ainda não o descobriu, mas tive alguns problemas para instalá-lo em alguns dos muitos servidores em que trabalho. (Eu esqueci o porquê: eu acho que relacionado aos módulos Perl necessários.)

Desde que eu não acho que trabalhei em uma caixa Unix que não tinha o Perl instalado (com a exceção de sistemas do tipo embedded, Linksys roteadores, e tal) eu diria que esta é uma solução universalmente utilizável.

    
por 24.07.2011 / 06:23
3

Em vez de usar o Grep, você pode usar Menos:

less file

Pesquise assim: /pattern Digite

Isto irá:

  1. role até a primeira linha correspondente
  2. imprima cada linha a partir daí em
  3. destacar todas as correspondências

Para rolar para a próxima linha correspondente: n

Para rolar para a linha correspondente anterior: N

Para alternar o realce: Esc u

Você também pode alterar a cor de destaque , se desejar.

    
por 04.02.2018 / 02:44
2

Você pode tentar:

perl -MTERM::ANSIColor -nle '/pattern/ ? print colored($_, 'color') : print' test

Não é muito portátil, no entanto, e mesmo se o Perl estiver instalado, talvez seja necessário baixar outro módulo. Além disso, irá colorir toda a linha, não apenas a palavra de pesquisa.

    
por 12.08.2010 / 05:09
2

ripgrep

Use ripgrep com seu parâmetro --passthru :

rg --passthru pattern file.txt

É uma das ferramentas de edição mais rápida , já que é construída sobre Regex engine do Rust que usa autômatos finitos, SIMD e otimizações literais agressivas para tornar a busca muito rápida.

--passthru - Print both matching and non-matching lines.

Another way to achieve a similar effect is by modifying your pattern to match the empty string. For example, if you are searching using rg foo then using rg "^|foo" instead will emit every line in every file searched, but only occurrences of foo will be highlighted. This flag enables the same behavior without needing to modify the pattern.

    
por 11.04.2018 / 11:52
1

Existe uma maneira muito mais fácil de fazer isso para o GNU grep, mas eu não acho que é portável (ou seja, BSD grep):

Em um pipe:

cat <file> | grep --color=always -z <query>

Em um arquivo:

grep --color=always -z <query> <file>

O crédito vai para resposta da Cyrus aqui .

    
por 26.09.2016 / 03:04
1

Nenhuma das respostas dadas até agora fornece uma solução portável .

Aqui está uma função de shell 1 portátil já publicada em um local fechado pergunta duplicada que não requer ferramentas não padrão ou extensões não padrão fornecidas com perl , ack , ggrep , gsed , bash e os gostos, mas precisa apenas de um shell POSIX e dos utilitários obrigatórios POSIX sed e printf :

grepc()
{
  pattern=$1
  shift
  esc=$(printf "3")
  sed 's"'"$pattern"'"'$esc'[32m&'$esc'[0m"g' "$@"
}

Você pode usá-lo dessa maneira:

grepc string_to_search [file ...]

A cor de destaque pode ser ajustada usando um desses códigos no argumento do comando sed (32m sendo verde aqui):

30m black
31m red
33m yellow
34m blue
35m magenta
36m cyan
37m white
7m reverse video

1 Contanto que o seu terminal suporte sequências de escape de cores ANSI.

    
por 20.11.2017 / 09:37
0

Uma versão sed , funciona em bash e ash .

#highlight
hsed(){
    local pattern="$1"
    shift
    local r='echo -e '\e'[31m'
    local c='echo -e '\e'[0m'
    sed "s:${pattern//:/\:}:$r
#highlight
hsed(){
    local pattern="$1"
    shift
    local r='echo -e '\e'[31m'
    local c='echo -e '\e'[0m'
    sed "s:${pattern//:/\:}:$r%pre%$c:g" "$@"
}
$c:g" "$@" }
    
por 30.12.2016 / 05:50
0

O OP pediu grep e é isso que RECOMENDO ; mas depois de tentar resolver um problema com sed , para constar, aqui está uma solução simples:

sed $'s/main/\E[31m&\E[0m/g' testt.c

ou

cat testt.c | sed $'s/main/\E[31m&\E[0m/g'

Pintará main em vermelho.

  • \E[31m : sequência inicial de cor vermelha
  • \E[0m : marca colorida finalizada
  • & : o padrão correspondente
  • /g : todas as palavras em uma linha, não apenas as primeiras
  • $'string' é strings bash com caracteres de escape interpretados

Em relação ao grep , ele também funciona usando ^ (início da linha) em vez de $ (fim da linha). Exemplo:

egrep "^|main" testt.c

E só para mostrar esse alias louco que NÃO RECOMENDO , você pode até deixar as aspas abertas:

alias h='egrep -e"^|'
h main" testt.c
cat testt.c | h main"

todo o trabalho! :) Não se preocupe se você esquecer de fechar a citação, bash vai lembrar de você com um "caractere de linha contínua".

    
por 20.11.2017 / 07:40