ファイルの差分ヘッド


11

2つのファイルがあります。おそらく、1つのファイルは他のファイルのサブセットです。最初のファイルの2番目のファイルが適合する場所を(簡潔に)識別するためにファイルを比較する方法はありますか?



1つのファイルの行が他のファイルのサブシーケンス、または実際には連続したサブストリングであることを意味しますか?
Kaz 2013年

連続する部分文字列、@ Kaz。
リチャード

回答:


14

diff -e bigger smaller トリックを実行しますが、出力は「有効なedスクリプト」であるため、ある程度の解釈が必要です。

「bigger」と「smaller」の2つのファイルを作成しました。「smaller」の内容は、「diff -e bigger small」を実行する「bigger」の5〜9行目と同じです。

% diff -e bigger smaller
10,15d
1,4d

これは、「 'bigger'の10行目から15行目を削除してから、1行目から4行目を削除して 'smaller'にすることを意味します。つまり、「小さい」は「大きい」の5行目から9行目です。

ファイル名を逆にすると、さらに複雑になります。「小さい」が「大きい」のサブセットを本当に構成している場合、「d」(削除)コマンドのみが出力に表示されます。


5

これはmeldで視覚的に行うことができます。残念ながら、これはGUIツールですが、これを1回だけ行いたい場合、比較的小さなファイルに対しては問題ありません。

以下の画像はの出力ですmeld a b

ここに画像の説明を入力してください


1
Meldは素晴らしいですが、100MB以上のファイルでは十分に再生できません。
Richard

@Richardいいえ、そうではありません。とにかくコマンドラインツールを使用したいと思います。
terdon

vimdiffターミナルで利用可能なによく似ています。
Patrick

2

ファイルが十分に小さい場合、Perlにそれらを丸呑みし、その正規表現エンジンにトリックを実行させることができます。

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";
'

-0777スイッチは、その入力レコードセパレータを設定するためにPerlを指示する$/完全SLURPファイルするように未定義の値に。


1
何をし777ますか?私はあなたがNULLを渡していると思いますが$/、なぜですか?また、これらはちょっと難解なスイッチなので、Perl以外の人には説明がいいでしょう。
terdon

1
@terdon私は実際にファイル全体を丸呑みにするためにそれをやっています。説明を追加しました。
ジョセフR.

しかし、なぜそれが必要なのでしょうか。$a=<$fh>とにかく右に丸呑みする必要がありますか?
terdon

1
@terdon私が知っていることではない、違う。デフォルトで$/は、ファイルの1行のみが読み取られる\nように設定されてい$a=<$fh>ます$fh。もちろん、perlコマンドラインの動作に私が知らない別のデフォルトがある場合を除きますか?
ジョセフR.

ああ、はい、私の悪いです。ファイルを丸呑みしたり、while $foo=<FILE>イディオムを使用したりすることはほとんどなかったので、確信が持てず、動作するように見える(間違った)テストを実行しました。気にしないで :)。
terdon

1

ファイルがテキストファイルでsmaller、内biggerで行の先頭から始まる場合、を使用して実装することはそれほど難しくありません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

1

あなたの質問は「Diff head of files」です。1つのファイルが他のファイルの先頭であることを本当に意味している場合は、単純なファイルでそれcmpがわかります。

cmp big_file small_file
cmp: EOF on small_file

これは、の読み取り中にファイルの終わりに達するまで、2つのファイルの違いが検出されなかったことを示していsmall_fileます。

ただし、小さなファイルのテキスト全体が内のどこにでも出現する可能性があるbig_file場合は、両方のファイルをメモリに収めることができると想定して、

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;
'

これはbig_file、のコンテンツsmall_fileが配置されている場所内のオフセットを出力します(たとえばsmall_file、の先頭に一致する場合は0 big_file)。small_file内部big_fileで一致しない場合、何も印刷されません。エラーがある場合、終了ステータスはゼロ以外になります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.