Formatando a saída do grep ao combinar em vários arquivos

4

Ao pesquisar em vários arquivos, a saída do grep é algo assim:

{FILE}:{MATCH}

Isso é um problema, pois se eu clicar duas vezes na porção {FILE} , pelo menos eu irei selecionar (e copiar) o : e possivelmente parte da correspondência. Como posso obter grep para formatar sua saída algo como isto:

{FILE} : {MATCH}

Basicamente, quero inserir um espaço antes da coluna. (e opcionalmente um depois)

    
por azani 18.11.2014 / 20:35

7 respostas

5

grep -T funcionará 7 / 8ths do tempo.

% for f in a ab abc abcd abcde abcdef abcdefg abcdefgh; do echo pattern > $f; done
% grep -T pattern *
a      :pattern
ab     :pattern
abc    :pattern
abcd   :pattern
abcde  :pattern
abcdef :pattern
abcdefg:pattern
abcdefgh       :pattern

No manual do GNU grep :

-T --initial-tab

Make sure that the first character of actual line content lies on a tab stop, so that the alignment of tabs looks normal. This is useful with options that prefix their output to the actual content: -H, -n, and -b. In order to improve the probability that lines from a single file will all start at the same column, this also causes the line number and byte offset (if present) to be printed in a minimum-size field width.

    
por 18.11.2014 / 21:21
6

Isso não pode ser feito por grep , até onde eu saiba. Supondo que seus nomes de arquivos não tenham : neles:

grep ... | sed 's/:/ : /'

Apenas o primeiro : será preenchido.

Claro, você pode dizer a grep para imprimir apenas nomes de arquivos:

grep -l ...
    
por 18.11.2014 / 20:58
5

O que constitui uma palavra , no que diz respeito à seleção com duplo clique, é terminal (e / ou X toolkit) dependente e, para alguns terminais, é customizável.

Para xterm , os caracteres são organizados em classes (letras, espaços ...) e o duplo clique seleciona os caracteres adjacentes da mesma classe.

O padrão é descrito . Nesse padrão, : não é na mesma classe que / não na mesma classe que letras ou dígitos.

Alguns sistemas alteram esse padrão fornecendo um arquivo de recursos para xterm como /etc/X11/app-defaults/XTerm .

Em um sistema Linux Mint, lá eu encontro:

! Here is a pattern that is useful for double-clicking on a URL:
*charClass: 33:48,35:48,37-38:48,43-47:48,58:48,61:48,63-64:48,95:48,126:48

Isso coloca os caracteres 58 ( : ) e 47 na mesma classe que letras e dígitos (48).

O que você pode fazer é alterar isso para deixar : em sua própria classe por meio de seu próprio arquivo de recursos.

Por exemplo, se você adicionar:

XTerm*charClass: 33:48,35:48,37-38:48,43-47:48,61:48,63-64:48,95:48,126:48

para o seu ~/".Xdefaults-$(uname -n)" e, em seguida, clique duas vezes no nome do arquivo e pare no : .

Você pode experimentar com:

xterm -cc 33:48,35:48,37-38:48,43-47:48,61:48,63-64:48,95:48,126:48

Você também pode definir um método de seleção diferente no clique triplo ou quádruplo como uma expressão regular. Por exemplo

XTerm*on3Clicks: regex [^:]+

Selecionaria sequências de caracteres não-cônicos após clique triplo .

    
por 18.11.2014 / 21:43
1

Awk funciona para mim:

grep string files | awk -F":" {'print $1" : "substr($0,index($0,$2))'}

Apenas um pouco de explicação, se seria útil: O formato {FILE}: {MATCH} de um multi-arquivo grep é canalizado para Awk. O awk é instruído a usar dois pontos (-F ":") como um delimitador para identificar campos e então a seguinte reformatação ocorre: Imprima o primeiro campo (FILE), depois imprima ":", depois imprima tudo até o final da linha começando onde o segundo campo (MATCH) começa. Isso deve ser responsável por vários ":" no jogo (obrigado muru).

    
por 18.11.2014 / 20:41
0

Como o muru disse, sed aceita fluxos de entrada aka. arquivos. Portanto, adicionar -l ao grep irá gerar arquivos em vez de texto. Pipe e use xargs .

grep -l ... | xargs sed 's/}:{/ : /'

Você pode precisar do parâmetro -i . Mais aqui .

Nota : Não é necessário escapar neste caso porque você não está usando expressões regulares nem o parâmetro -e para sed , por isso ele procura apenas o que você colocar lá. É mais seguro incluir as chaves , pois o texto também pode ter ponto-e-vírgula.

    
por 18.11.2014 / 21:27
0

Eu passaria a saída do comando grep para o Perl, como abaixo.

grep ... | perl -pe 's/(?<=:)|(?=:)/ /g'

Exemplo:

$ echo '{FILE}:{MATCH}' | perl -pe 's/(?<=:)|(?=:)/ /g'
{FILE} : {MATCH}

Explicação:

  • (?<=:) Corresponde ao limite que existe após :
  • | OR
  • (?=:) Corresponde ao limite que existe antes de :
  • Substitua todos os limites correspondidos por um espaço.
por 19.11.2014 / 04:31
0

Isso é extremamente ineficiente como resulta em gerar um novo processo grep para cada arquivo de entrada, mas:

Dada uma lista de arquivos (por exemplo, * ), faça

for f in file_list
do
    grep --label="$f " --with-filename pattern < "$f"
done

--label=string diz: com efeito, “Ao ler a entrada padrão, finja que o nome do arquivo de entrada é string . ” --with-filename ( -H para breve) diz: "Imprima o nome do arquivo para cada correspondência". Este é o padrão quando há mais de um arquivo para pesquisar. IMNSHO, ele também deve estar ativado por padrão quando você especifica --label , mas parece que não funciona assim. Já que meu código (acima) adiciona um espaço ao nome do arquivo no argumento para --label , você obtém uma saída parecida com

filename :Line matching pattern

Se os nomes dos seus arquivos forem provenientes de find , faça

find (path…) (expression) -exec sh -c 'grep --label="$1 " -H pattern < "$1"' sh {} ";"
    
por 19.11.2014 / 02:03

Tags