Eu tenho dois arquivos Suspeito que um arquivo seja 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?
Você quer dizer que as linhas de um arquivo são uma subsequência do outro ou, na verdade, uma substring contígua?
Kaz
Uma substring contígua, @Kaz.
Richard
Respostas:
14
diff -e bigger smaller fará o truque, mas requer alguma interpretação, pois a saída é um "script ed válido".
Eu criei dois arquivos, "maior" e "menor", em que o conteúdo de "menor" é idêntico às linhas 5 a 9 de "maior", fazendo `diff -e maior menor":
% diff -e bigger smaller
10,15d
1,4d
O que significa "exclua as linhas 10 a 15 de 'maior' e exclua as linhas 1 a 4 para ficar 'menor'". Isso significa "menor" são as linhas 5 a 9 de "maior".
Inverter os nomes dos arquivos me deu algo mais complicado. Se "menor" realmente constituir um subconjunto de "maior", apenas os comandos 'd' (para excluir) serão exibidos na saída.
Você pode fazer isso visualmente com meld . Infelizmente, é uma ferramenta da GUI, mas se você quiser fazer isso apenas uma vez e em um arquivo relativamente pequeno, tudo ficará bem:
Meld é legal, mas não funciona tão bem com arquivos com mais de 100 MB.
Richard
@ Richard não, não e eu preferiria uma ferramenta de linha de comando de qualquer maneira, eu apenas pensei em mencionar.
terdon
Parece muito vimdiff, que está disponível no terminal.
Patrick
2
Se os arquivos forem pequenos o suficiente, você poderá incorporá-los ao Perl e fazer com que seu mecanismo de regex faça o seguinte:
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";
'
O -0777comutador instrui o Perl a definir seu separador de registros de entrada $/para o valor indefinido, a fim de eliminar completamente os arquivos.
O que 777faz? Presumo que você está passando NULL como $/mas por quê? Além disso, como são opções esotéricas, uma explicação seria boa para as pessoas não-perl.
terdon
1
@terdon Estou realmente fazendo isso para consumir os arquivos inteiros. Explicação adicionada.
Joseph R.
Mas por que isso é necessário? $a=<$fh>deve beber assim mesmo, certo?
terdon
1
@terdon Não que eu saiba, não. Por padrão, $/é definido como \npara que $a=<$fh>apenas uma linha do arquivo $fhseja aberta. A menos que perlo comportamento da linha de comando do curso tenha padrões diferentes dos quais eu não conheço?
Joseph R.
Argh, sim, meu mal, eu quase nunca sorvo arquivos ou uso o while $foo=<FILE>idioma, então não tinha certeza e executei um teste (errado) que parecia funcionar. Deixa pra lá :).
terdon
1
Se os arquivos são de texto e smaller, dentro de biggerinicia no início de uma linha, não é muito difícil implementar com awk:
Sua pergunta é "Diff head of files". Se você realmente quer dizer que um arquivo é a cabeça do outro, um simples cmpdirá que:
cmp big_file small_file
cmp: EOF on small_file
Isso informa que uma diferença entre os dois arquivos não foi detectada até o final do arquivo ser alcançado durante a leitura small_file.
Se, no entanto, você quer dizer que todo o texto do arquivo pequeno pode ocorrer em qualquer lugar big_file, pressupondo que você possa ajustar os dois arquivos na memória, use
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 no local big_fileonde o conteúdo small_fileestá localizado (por exemplo, 0 se small_filecorresponder no início de big_file). Se small_filenão corresponder ao interior big_file, nada será impresso. Se houver um erro, o status de saída será diferente de zero.
Respostas:
diff -e bigger smaller
fará o truque, mas requer alguma interpretação, pois a saída é um "script ed válido".Eu criei dois arquivos, "maior" e "menor", em que o conteúdo de "menor" é idêntico às linhas 5 a 9 de "maior", fazendo `diff -e maior menor":
O que significa "exclua as linhas 10 a 15 de 'maior' e exclua as linhas 1 a 4 para ficar 'menor'". Isso significa "menor" são as linhas 5 a 9 de "maior".
Inverter os nomes dos arquivos me deu algo mais complicado. Se "menor" realmente constituir um subconjunto de "maior", apenas os comandos 'd' (para excluir) serão exibidos na saída.
fonte
Você pode fazer isso visualmente com meld . Infelizmente, é uma ferramenta da GUI, mas se você quiser fazer isso apenas uma vez e em um arquivo relativamente pequeno, tudo ficará bem:
A imagem abaixo é a saída de
meld a b
:fonte
vimdiff
, que está disponível no terminal.Se os arquivos forem pequenos o suficiente, você poderá incorporá-los ao Perl e fazer com que seu mecanismo de regex faça o seguinte:
O
-0777
comutador instrui o Perl a definir seu separador de registros de entrada$/
para o valor indefinido, a fim de eliminar completamente os arquivos.fonte
777
faz? Presumo que você está passando NULL como$/
mas por quê? Além disso, como são opções esotéricas, uma explicação seria boa para as pessoas não-perl.$a=<$fh>
deve beber assim mesmo, certo?$/
é definido como\n
para que$a=<$fh>
apenas uma linha do arquivo$fh
seja aberta. A menos queperl
o comportamento da linha de comando do curso tenha padrões diferentes dos quais eu não conheço?while $foo=<FILE>
idioma, então não tinha certeza e executei um teste (errado) que parecia funcionar. Deixa pra lá :).Se os arquivos são de texto e
smaller
, dentro debigger
inicia no início de uma linha, não é muito difícil implementar comawk
:fonte
Sua pergunta é "Diff head of files". Se você realmente quer dizer que um arquivo é a cabeça do outro, um simples
cmp
dirá que:Isso informa que uma diferença entre os dois arquivos não foi detectada até o final do arquivo ser alcançado durante a leitura
small_file
.Se, no entanto, você quer dizer que todo o texto do arquivo pequeno pode ocorrer em qualquer lugar
big_file
, pressupondo que você possa ajustar os dois arquivos na memória, useIsso imprimirá o deslocamento no local
big_file
onde o conteúdosmall_file
está localizado (por exemplo, 0 sesmall_file
corresponder no início debig_file
). Sesmall_file
não corresponder ao interiorbig_file
, nada será impresso. Se houver um erro, o status de saída será diferente de zero.fonte