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?
¿Quiere decir que las líneas de un archivo son una subsecuencia del otro, o en realidad una subcadena contigua?
Kaz
Una subcadena contigua, @Kaz.
Richard
Respuestas:
14
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:
¿Qué 777hacer? 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.
terdon
1
@terdon De hecho, lo estoy haciendo para sorber los archivos completos. Explicación agregada.
Joseph R.
¿Pero por qué es eso necesario? $a=<$fh>debería sorber de todos modos, ¿verdad?
terdon
1
@terdon No que yo sepa, no. De manera predeterminada, $/se establece en de \nmodo que $a=<$fh>solo se $fhabrirí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.
Joseph R.
Argh, sí, mi mal, casi nunca sorbo archivos o uso el while $foo=<FILE>idioma, así que no estaba seguro y realicé una prueba (incorrecta) que parecía funcionar. No importa :).
terdon
1
Si los archivos son archivos de texto y smaller, al biggercomenzar al principio de una línea, no es demasiado difícil de implementar con awk:
Su pregunta es "Diff head of files". Si realmente quiere decir que un archivo es la cabeza del otro, entonces un simple cmple 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_filedonde se encuentran los contenidos de small_file(por ejemplo, 0 si small_filecoincide al principio de big_file). Si small_fileno coincide dentro big_file, entonces no se imprimirá nada. Si hay un error, el estado de salida será distinto de cero.
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ó:
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.
fuente
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
:fuente
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:
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.fuente
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 supuestoperl
, 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
, albigger
comenzar al principio de una línea, no es demasiado difícil de implementar conawk
:fuente
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: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 usarEsto imprimirá el desplazamiento dentro de
big_file
donde se encuentran los contenidos desmall_file
(por ejemplo, 0 sismall_file
coincide al principio debig_file
). Sismall_file
no coincide dentrobig_file
, entonces no se imprimirá nada. Si hay un error, el estado de salida será distinto de cero.fuente