Grepping várias instâncias de uma string, com contexto, de um arquivo

1

Eu tenho um arquivo de despejo MySQL, que é principalmente instruções INSERT. Eu quero grep out instâncias da cadeia 'media' de um campo em uma tabela particular, com + / - 10 caracteres de contexto. A cadeia pode aparecer várias vezes no valor da coluna. Como posso fazer isso?

A origem é um arquivo sql dump extremamente grande (terei que truncar severamente por brevidade):

INSERT...334,'field_media_intro_image','image','image'...);
INSERT...g__vieg__view_mode__media_original attr__format....ategies that are immediately actionable for the task...);

Eu gostaria de ver

ield_media_intr
ode__media_orig, re immediately 

Onde a primeira linha acima é a única instância da string 'media' na primeira linha correspondente, e a segunda linha mostra as duas instâncias da string 'media', a partir da próxima linha correspondente. Ambos mostram cinco caracteres de contexto no início e no final da string. A vírgula funciona como um separador.

    
por user394 14.05.2015 / 20:21

1 resposta

1

___ qstnhdr ___ Grepping várias instâncias de uma string, com contexto, de um arquivo ______ qstntxt ___

Eu tenho um arquivo de despejo MySQL, que é principalmente instruções INSERT. Eu quero grep out instâncias da cadeia 'media' de um campo em uma tabela particular, com + / - 10 caracteres de contexto. A cadeia pode aparecer várias vezes no valor da coluna. Como posso fazer isso?

A origem é um arquivo sql dump extremamente grande (terei que truncar severamente por brevidade):

grep -Eo '.{0,10}media.{0,10}'

Eu gostaria de ver

$ echo 123 media 12345 media 123456789 media 12 |grep -Eo '.{0,10}media.{0,10}'
123 media 12345 med
234567890 media 123

Onde a primeira linha acima é a única instância da string 'media' na primeira linha correspondente, e a segunda linha mostra as duas instâncias da string 'media', a partir da próxima linha correspondente. Ambos mostram cinco caracteres de contexto no início e no final da string. A vírgula funciona como um separador.

    
______ azszpr266939 ___

GNU grep pode capturar o contexto por linhas ( -A LINES para o contexto depois , -B LINES para o contexto antes e -C LINES para contexto antes e depois), mas não tem um sinalizador para o contexto horizontal. Você pode fazer isso com um regex:

$ echo 123 media 12345 media 123456789 media 12 |grep -Po '.{0,10}?media.{0,10}?'
123 media
 12345 media
234567890 media

( -E usa Expressões regulares estendidas (ERE), permitindo a sintaxe como .{0,10} (correspondência qualquer caractere 0 a 10 vezes.) O -o do GNU grep exibe somente o conteúdo correspondente, uma correspondência por linha.

Greediness

Note que esta não será uma lista abrangente, pois algumas cópias da palavra "mídia" podem estar muito próximas do que já foi capturado. Por exemplo:

$ echo 123 media 123 media 123456789 media 12 |perl -ne \
    'while (/(.{0,10}?media.{0,10}?)/g) { print "$1\n"; }'
123 media
 12345 media
234567890 media

Você obtém partes de todas as três instâncias de "mídia", mas como uma delas está parcialmente dentro de dez caracteres de outra, apenas essa parte dela foi representada.

Se o compilador GNU grep estiver compilado com a biblioteca C veja também o link da Wikipédia no PCRE seguindo este bloco de código"> libpcre , você pode dizer que esses curingas são preguiçoso ao invés de ganancioso :

grep -Eo '.{0,10}media.{0,10}'

A sinalização -P permite a avaliação Expressão regular compatível com Perl (PCRE).

A avaliação preguiçosa (também chamada de "avaliação não-gananciosa") aspira evitar que uma correspondência interfira com outra, em vez de consumir o máximo de dez caracteres possíveis, o que limita outras combinações.

Se a sua versão de grep não for compatível com -P ou -o , você poderá usar perl :

$ echo 123 media 12345 media 123456789 media 12 |grep -Eo '.{0,10}media.{0,10}'
123 media 12345 med
234567890 media 123

Isso modifica o regex para incluir um grupo correspondente, para que possamos nos referir ao texto correspondente mais tarde. Caso contrário, é apenas um loop em cada partida (o g corresponde globalmente, e não apenas na primeira vez), que então imprime a partida com uma nova linha.

GNU vs POSIX grep

O

GNU grep adiciona muita funcionalidade sobre o padrão grep POSIX . Específico para essa resposta, -A LINES (linhas de contexto a fter), -B LINES (linhas de contexto b antes), -C LINES (linhas de c ontext antes e depois), -o (show o apenas a correspondência) e -P (use P CRE) estão todos disponíveis em GNU grep mas não pode ser assumido para outras implementações do grep. O BSD grep suporta todos eles, exceto -P , mas o GNU grep é frequentemente preferido pelos usuários do BSD devido a Otimizações de desempenho do GNU .

Os comandos GNU e BSD grep também suportam --color , que você pode usar como uma alternativa para -o . Isso terminará exibindo linhas inteiras com o texto correspondente ("mídia" e seus 0 a 10 caracteres de contexto) colorido.

Uma nota final: Um comentário à pergunta usou a sintaxe .{,5} , que funciona em grep -E , mas quase em nenhum outro lugar (certamente nem grep -P nem perl ). É um mau hábito usar esse formato em vez de incluir explicitamente o zero em .{0,5} .

    
___
por 02.03.2016 / 02:48