Eu tenho alguns despejos de banco de dados de um sistema Windows na minha caixa. Eles são arquivos de texto. Estou usando o cygwin para cumprimentá-los. Estes parecem ser arquivos de texto simples; Abro-os com editores de texto, como o bloco de notas e o wordpad, e eles parecem legíveis. No entanto, quando eu executo grep, eles dirão binary file foo.txt matches
.
Percebi que os arquivos contêm alguns NUL
caracteres ASCII , que acredito serem artefatos do despejo de banco de dados.
Então, o que faz o grep considerar esses arquivos como binários? O NUL
personagem? Existe uma bandeira no sistema de arquivos? O que preciso alterar para que o grep me mostre as correspondências da linha?
--null-data
pode ser útil seNUL
for o delimitador.Respostas:
Se houver um
NUL
caractere em qualquer lugar do arquivo, o grep o considerará um arquivo binário.Pode haver uma solução alternativa como essa
cat file | tr -d '\000' | yourgrep
para eliminar todos os nulos primeiro e depois pesquisar no arquivo.fonte
-a
/--text
, pelo menos com o GNU grep.NUL
(provavelmente porque chama o printf de C e fornece a linha correspondente?). Nesse sistema, agrep cmd .sh_history
retornará quantas linhas vazias houver linhas correspondentes a 'cmd', pois cada linha de sh_history possui um formato específico com aNUL
no início de cada linha. (mas o seu comentário "pelo menos no GNU grep" provavelmente vem verdade eu não tiver um na mão agora para testar, mas espero que eles lidar com isso muito bem.)grep
no cygwin considerava binário porque tinha um traço longo (0x96) em vez de um hífen ASCII normal / menos (0x2d). Acho que essa resposta resolveu o problema do OP, mas parece que está incompleto.grep -a
trabalhou para mim:fonte
Você pode usar o
strings
utilitário para extrair o conteúdo de texto de qualquer arquivo e depois canalizá-lo através degrep
, como este:strings file | grep pattern
.fonte
GNU grep 2.24 RTFS
Conclusão: 2 e 2 casos apenas:
NUL
, por exemploprintf 'a\0' | grep 'a'
erro de codificação de acordo com o C99
mbrlen()
, por exemplo:porque
\x80
não pode ser o primeiro byte de um ponto Unicode UTF-8 : UTF-8 - Descrição | en.wikipedia.orgAlém disso, como mencionado por Stéphane Chazelas O que faz o grep considerar um arquivo como binário? | Unix e Linux Stack Exchange , essas verificações são feitas apenas até a primeira leitura do buffer com o comprimento TODO.
Somente até a primeira leitura do buffer
Portanto, se ocorrer um erro de codificação ou NUL no meio de um arquivo muito grande, ele poderá ser recebido de qualquer maneira.
Eu imagino que isso seja por razões de desempenho.
Por exemplo: isso imprime a linha:
mas isso não:
O tamanho real do buffer depende de como o arquivo é lido. Por exemplo, compare:
Com o
sleep
, a primeira linha é passada para o grep, mesmo que tenha apenas 1 byte, porque o processo entra no modo de espera ea segunda leitura não verifica se o arquivo é binário.RTFS
Localize onde a mensagem de erro stderr está codificada:
Nos leva a
/src/grep.c
:Se essas variáveis foram bem nomeadas, chegamos basicamente à conclusão.
encoding_error_output
O grepping rápido para
encoding_error_output
mostra que o único caminho de código que pode modificá-lo passa porbuf_has_encoding_errors
:então apenas
man mbrlen
.nlines_first_null e nlines
Inicializado como:
portanto, quando um nulo é encontrado,
0 <= nlines_first_null
torna-se verdadeiro.TODO quando pode
nlines_first_null < nlines
ser falso? Eu fiquei com preguiçaPOSIX
Não define opções binárias grep - pesquisa um padrão em um arquivo | pubs.opengroup.org e GNU grep não o documentam, então o RTFS é a única maneira.
fonte
(printf '\n\0y') | grep y
com,(printf '\n'; sleep 1; printf '\0y') | grep y
por exemplo.export LC_CTYPE='en_US.UTF-8'
como no meu exemplo, ou algo mais? Buf read: amazing example, added to answer. Você, obviamente, ler a fonte mais do que eu, me lembra daqueles koans hackers "O estudante estava iluminado" :-)Um dos meus arquivos de texto foi subitamente visto como binário pelo grep:
A solução foi convertê-lo usando
iconv
:fonte
0xFC
hexadecimal, portanto, fora do intervalo, o grep esperaria pelo utf8 (até0x7F
). Verifique com printf 'a \ x7F' | grep 'a' como Ciro descreve acima.O arquivo
/etc/magic
ou/usr/share/misc/magic
possui uma lista de sequências que o comandofile
usa para determinar o tipo de arquivo.Observe que o binário pode ser apenas uma solução alternativa. Às vezes, arquivos com codificação estranha também são considerados binários.
grep
no Linux tem algumas opções para lidar com arquivos binários como--binary-files
ou-U / --binary
fonte
mbrlen()
. Exemplo e interpretação da fonte em: unix.stackexchange.com/a/276028/32558Um dos meus alunos teve esse problema. Há um erro
grep
noCygwin
. Se o arquivo tiver caracteres não-Ascii,grep
eegrep
veja-o como binário.fonte
Na verdade, respondendo à pergunta "O que faz o grep considerar um arquivo como binário?", Você pode usar
iconv
:No meu caso, havia caracteres em espanhol que apareciam corretamente nos editores de texto, mas o grep os considerava binários;
iconv
saída me apontou para os números de linha e coluna desses caracteresNo caso de
NUL
caracteres,iconv
considerá-los-á normais e não imprimirá esse tipo de saída, portanto esse método não é adequadofonte
Eu tive o mesmo problema. Eu costumava
vi -b [filename]
ver os caracteres adicionados. Eu encontrei os caracteres de controle^@
e^M
. Em seguida, no tipo vi,:1,$s/^@//g
para remover os^@
caracteres. Repita este comando para^M
.Aviso: Para obter os caracteres de controle "azuis", pressione Ctrl+ ve Ctrl+ Mou Ctrl+ @. Em seguida, salve e saia do vi.
fonte