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 -0777switch 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 \nmodo 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 biggercomincia 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 cmpti 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_filepunto in cui small_filesi trova il contenuto di (ad es. 0 se small_filecorrisponde all'inizio di big_file). Se small_filenon corrisponde all'interno big_file, non verrà stampato nulla. Se si verifica un errore, lo stato di uscita sarà diverso da zero.