Tengo dos archivos Sospecho que un archivo es un subconjunto del otro. ¿Hay alguna manera de diferenciar los archivos para identificar (de manera sucinta) dónde en el primer archivo cabe el segundo archivo?
Tengo dos archivos Sospecho que un archivo es un subconjunto del otro. ¿Hay alguna manera de diferenciar los archivos para identificar (de manera sucinta) dónde en el primer archivo cabe el segundo archivo?
Respuestas:
diff -e bigger smaller
hará el truco, pero requiere cierta interpretación, ya que el resultado es un "script ed válido".
Hice dos archivos, "más grande" y "más pequeño", donde el contenido de "más pequeño" es idéntico a las líneas 5 a 9 de "más grande" haciendo 'diff -e más grande más pequeño "me consiguió:
% diff -e bigger smaller
10,15d
1,4d
Lo que significa "eliminar las líneas 10 a 15 de 'más grande', y luego eliminar las líneas 1 a 4, para obtener 'más pequeño'". Eso significa que "más pequeño" son las líneas 5 a 9 de "más grande".
Invertir los nombres de los archivos me dio algo más complicado. Si "más pequeño" realmente constituye un subconjunto de "más grande", solo los comandos 'd' (para eliminar) aparecerán en la salida.
Puedes hacer esto visualmente con meld . Desafortunadamente, es una herramienta GUI, pero si solo quieres hacer esto una vez, y en un archivo relativamente pequeño, debería estar bien:
La siguiente imagen es la salida de meld a b
:
vimdiff
, que está disponible en la terminal.
Si los archivos son lo suficientemente pequeños, puede arrastrarlos a Perl y hacer que su motor de expresiones regulares haga el truco:
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";
'
El -0777
conmutador le indica a Perl que establezca su separador de registro de entrada $/
en el valor indefinido para sorber los archivos por completo.
777
hacer? Supongo que estás pasando NULL, $/
pero ¿por qué? Además, dado que estos son interruptores esotéricos, una explicación sería buena para las personas que no son perl.
$a=<$fh>
debería sorber de todos modos, ¿verdad?
$/
se establece en de \n
modo que $a=<$fh>
solo se $fh
abriría una línea del archivo . A menos que, por supuesto perl
, el comportamiento de la línea de comandos tenga valores predeterminados diferentes que desconozco.
while $foo=<FILE>
idioma, así que no estaba seguro y realicé una prueba (incorrecta) que parecía funcionar. No importa :).
Si los archivos son archivos de texto y smaller
, al bigger
comenzar al principio de una línea, no es demasiado difícil de implementar con 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
Su pregunta es "Diff head of files". Si realmente quiere decir que un archivo es la cabeza del otro, entonces un simple cmp
le dirá que:
cmp big_file small_file
cmp: EOF on small_file
Eso le dice que no se detectó una diferencia entre los dos archivos hasta que se alcanzó el final del archivo mientras se leía small_file
.
Sin embargo, si quiere decir que todo el texto del archivo pequeño puede aparecer en cualquier parte del interior big_file
, suponiendo que pueda guardar ambos archivos en la memoria, puede 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;
'
Esto imprimirá el desplazamiento dentro de big_file
donde se encuentran los contenidos de small_file
(por ejemplo, 0 si small_file
coincide al principio de big_file
). Si small_file
no coincide dentro big_file
, entonces no se imprimirá nada. Si hay un error, el estado de salida será distinto de cero.