Diff head de arquivos

11

Eu tenho dois arquivos. Um arquivo, suspeito, é um subconjunto do outro. Existe uma maneira de diferenciar os arquivos para identificar (de maneira sucinta) onde no primeiro arquivo o segundo arquivo se encaixa?

    
por Richard 29.10.2013 / 20:25

5 respostas

13

diff -e bigger smaller fará o truque, mas requer alguma interpretação, já que a saída é um "script ed válido".

Eu fiz dois arquivos, "maior" e "menor", onde o conteúdo de "menor" é idêntico às linhas 5 a 9 de "maior" fazendo "diff -e menor menor" me pegou:

% diff -e bigger smaller
10,15d
1,4d

O que significa "apague as linhas 10 a 15 de 'maior' e depois apague as linhas de 1 a 4 para ficar 'menor'". Isso significa que "menor" é linhas de 5 a 9 de "maior".

Reverter os nomes dos arquivos me trouxe algo mais complicado. Se "menor" realmente constitui um subconjunto de "maior", somente os comandos "d" (para exclusão) aparecerão na saída.

    
por 29.10.2013 / 20:44
5

Você pode fazer isso visualmente com meld . Infelizmente, é uma ferramenta de GUI, mas se você quiser fazer isso apenas uma vez e em um arquivo relativamente pequeno, tudo bem:

A imagem abaixo é a saída de meld a b :

    
por 29.10.2013 / 20:47
2

Se os arquivos forem pequenos o suficiente, você pode fazer o slurp deles em Perl e fazer com que seu mecanismo de regex funcione:

perl -0777e '
        open "$FILE1","<","file_1";
        open "$FILE2","<","file_2";
        $file_1 = <$FILE1>;
        $file_2 = <$FILE2>;
        print "file_2 is", $file_1 =~ /\Q$file_2\E/ ? "" : "not";
        print " a subset of file_1\n";
'

A opção -0777 instrui o Perl a definir seu separador de registro de entrada $/ como o valor indefinido, de modo a fazer slurp de arquivos completamente.

    
por 29.10.2013 / 20:50
1

Se os arquivos forem arquivos de texto e smaller , dentro de bigger começa no início de uma linha, não é muito difícil implementar com awk :

awk -v i=0 'NR==FNR{l[n++]=$0;next}
    {if ($0 == l[i]) {if (++i == n) {print FNR-n+1;exit}} else i=0}
    ' smaller bigger
    
por 29.10.2013 / 22:14
1

Sua pergunta é "Diff head of files". Se você realmente quer dizer que um arquivo é a cabeça do outro, então um simples cmp dirá a você que:

cmp big_file small_file
cmp: EOF on small_file

Isso informa que a diferença entre os dois arquivos não foi detectada até que o fim do arquivo foi atingido durante a leitura de small_file .

Se, no entanto, você quer dizer que todo o texto do arquivo pequeno pode ocorrer em qualquer lugar dentro de big_file , presumindo que você pode ajustar ambos os arquivos na memória, você pode usar

perl -le '
   use autodie;
   undef $/;
   open SMALL, "<", "small_file";
   open BIG, "<", "big_file";
   $small = <SMALL>;
   $big = <BIG>;
   $pos = index $big, $small;
   print $pos if $pos >= 0;
'

Isso imprimirá o deslocamento em big_file , onde o conteúdo de small_file está localizado (por exemplo, 0 se small_file corresponder no início de big_file ). Se small_file não corresponder dentro de big_file , nada será impresso. Se houver um erro, o status de saída será diferente de zero.

    
por 05.11.2013 / 23:35

Tags