Ho due file. Un file, sospetto, è un sottoinsieme dell'altro. C'è un modo per diffondere i file per identificare (in modo sintetico) dove nel primo file si adatta il secondo file?
Ho due file. Un file, sospetto, è un sottoinsieme dell'altro. C'è un modo per diffondere i file per identificare (in modo sintetico) dove nel primo file si adatta il secondo file?
Risposte:
diff -e bigger smaller
farà il trucco, ma richiede una certa interpretazione, poiché l'output è uno "script ed valido".
Ho creato due file, "più grande" e "più piccolo", in cui il contenuto di "più piccolo" è identico alle righe da 5 a 9 di "più grande" che fa "diff -e più grande" mi ha fatto:
% diff -e bigger smaller
10,15d
1,4d
Il che significa "elimina le righe da 10 a 15 di" più grande ", quindi elimina le righe da 1 a 4, per ottenere" più piccolo "". Ciò significa che "più piccolo" è le righe da 5 a 9 di "più grande".
Invertire i nomi dei file mi ha reso qualcosa di più complicato. Se "più piccolo" costituisce veramente un sottoinsieme di "più grande", nell'output verranno visualizzati solo i comandi "d" (per l'eliminazione).
Puoi farlo visivamente con la fusione . Sfortunatamente, è uno strumento GUI ma se vuoi farlo una volta sola, e su un file relativamente piccolo, dovrebbe andare bene:
L'immagine seguente è l'output di meld a b
:
vimdiff
, disponibile nel terminale.
Se i file sono abbastanza piccoli, puoi inserirli entrambi in Perl e fare in modo che il suo motore regex faccia il trucco:
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";
'
Lo -0777
switch indica a Perl di impostare il separatore del record di input $/
sul valore indefinito in modo da snellire completamente i file.
777
? Suppongo che stai passando NULL come, $/
ma perché? Anche dal momento che si tratta di interruttori esoterici, una spiegazione sarebbe utile per le persone non perl.
$a=<$fh>
dovrebbe bere comunque?
$/
è impostato in \n
modo da $a=<$fh>
leggere solo una riga del file $fh
. A meno che, naturalmente perl
, il comportamento della riga di comando abbia impostazioni predefinite diverse di cui non sono a conoscenza?
while $foo=<FILE>
linguaggio quindi non ero sicuro e ho eseguito un test (sbagliato) che sembrava funzionare. Non importa :).
Se i file sono file di testo e smaller
, all'interno bigger
comincia all'inizio di una riga, non è troppo difficile da attuare 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
La tua domanda è "Diff head of files". Se davvero intendi che un file è il capo dell'altro, allora un semplice cmp
ti dirà che:
cmp big_file small_file
cmp: EOF on small_file
Ciò indica che non è stata rilevata una differenza tra i due file fino a quando non è stata raggiunta la fine del file durante la lettura small_file
.
Se tuttavia vuoi dire che l'intero testo di un piccolo file può essere presente ovunque all'interno big_file
, quindi supponendo che tu possa adattare entrambi i file in memoria, puoi usare
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;
'
Questo stamperà l'offset all'interno del big_file
punto in cui small_file
si trova il contenuto di (ad es. 0 se small_file
corrisponde all'inizio di big_file
). Se small_file
non corrisponde all'interno big_file
, non verrà stampato nulla. Se si verifica un errore, lo stato di uscita sarà diverso da zero.