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?
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?
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":
% 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:
A imagem abaixo é a saída de meld a b
:
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:
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 -0777
comutador instrui o Perl a definir seu separador de registros de entrada $/
para o valor indefinido, a fim de eliminar completamente os arquivos.
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 que perl
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 de bigger
inicia 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
Sua pergunta é "Diff head of files". Se você realmente quer dizer que um arquivo é a cabeça do outro, um simples cmp
dirá 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_file
onde o conteúdo small_file
está localizado (por exemplo, 0 se small_file
corresponder no início de big_file
). Se small_file
não corresponder ao interior big_file
, nada será impresso. Se houver um erro, o status de saída será diferente de zero.