Đầu tập tin


11

Tôi có hai tập tin. Một tập tin, tôi nghi ngờ, là một tập hợp con khác. Có cách nào để khuếch tán các tập tin để xác định (một cách cô đọng) trong tập tin thứ nhất tập tin thứ hai không?



Bạn có nghĩa là các dòng của một tệp là một chuỗi con khác, hoặc thực sự là một chuỗi con liền kề?
Kaz

Một chuỗi con liền kề, @Kaz.
Richard

Câu trả lời:


14

diff -e bigger smaller sẽ thực hiện thủ thuật, nhưng yêu cầu một số giải thích, vì đầu ra là "tập lệnh ed hợp lệ".

Tôi đã tạo hai tệp "lớn hơn" và "nhỏ hơn", trong đó nội dung của "nhỏ hơn" giống hệt với dòng 5 đến 9 của "lớn hơn" khi thực hiện `diff -e lớn hơn nhỏ hơn" cho tôi:

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

Có nghĩa là "xóa các dòng 10 đến 15 của 'lớn hơn', và sau đó xóa các dòng từ 1 đến 4, để có được 'nhỏ hơn'". Điều đó có nghĩa là "nhỏ hơn" là dòng 5 đến 9 của "lớn hơn".

Đảo ngược tên tập tin đã cho tôi một cái gì đó phức tạp hơn. Nếu "nhỏ hơn" thực sự tạo thành một tập hợp con "lớn hơn", chỉ các lệnh 'd' (để xóa) sẽ hiển thị trong đầu ra.


5

Bạn có thể làm điều này trực quan với meld . Thật không may, nó là một công cụ GUI nhưng nếu bạn chỉ muốn làm điều này một lần và trên một tệp tương đối nhỏ, nó sẽ ổn:

Hình ảnh dưới đây là đầu ra của meld a b:

nhập mô tả hình ảnh ở đây


1
Meld rất đẹp, nhưng nó không chơi tốt với các tệp 100MB +.
Richard

@Richard không có nó và tôi thích một công cụ dòng lệnh hơn, tôi chỉ nghĩ rằng tôi sẽ đề cập đến nó.
terdon

Trông rất giống vimdiff, có sẵn trong thiết bị đầu cuối.
Patrick

2

Nếu các tệp đủ nhỏ, bạn có thể nhét cả hai vào Perl và để công cụ regex của nó thực hiện thủ thuật:

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

Công -0777tắc hướng dẫn Perl thiết lập dấu tách bản ghi đầu vào của nó $/thành giá trị không xác định để làm mờ hoàn toàn các tệp.


1
Không gì 777làm gì? Tôi nhận nó bạn đang vượt qua NULL như $/tại sao? Ngoài ra vì đây là những công tắc bí truyền, nên một lời giải thích sẽ tốt cho những người không phải là người perl.
terdon

1
@terdon Tôi thực sự đang làm điều đó để làm lu mờ toàn bộ tập tin. Giải thích thêm.
Joseph R.

Nhưng tại sao điều đó lại cần thiết? $a=<$fh>Dù sao cũng nên nhếch nhác phải không?
terdon

1
@terdon Không phải tôi biết, không. Theo mặc định $/là thiết lập để \nsao cho $a=<$fh>có thể chỉ đọc một dòng của tập tin $fhđã được mở ra cho. Trừ khi perlhành vi dòng lệnh của khóa học có các mặc định khác nhau mà tôi không biết?
Joseph R.

Argh, vâng, thật tệ, tôi gần như không bao giờ đọc các tập tin hoặc sử dụng while $foo=<FILE>thành ngữ này vì vậy tôi không chắc chắn và đã chạy một bài kiểm tra (sai) có vẻ hiệu quả. Đừng bận tâm :).
terdon

1

Nếu các tệp là tệp văn bản và smaller, biggerbắt đầu ở đầu dòng, không quá khó để thực hiện với 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

Câu hỏi của bạn là "Diff head of files". Nếu bạn thực sự muốn nói rằng một tệp là đầu của tệp kia, thì một đơn giản cmpsẽ cho bạn biết rằng:

cmp big_file small_file
cmp: EOF on small_file

Điều đó cho bạn biết rằng không tìm thấy sự khác biệt giữa hai tệp cho đến khi đạt đến cuối tệp trong khi đọc small_file.

Tuy nhiên, nếu bạn có nghĩa là toàn bộ văn bản của tệp nhỏ có thể xảy ra ở bất kỳ đâu bên trong big_file, thì giả sử bạn có thể vừa cả hai tệp trong bộ nhớ, bạn có thể sử dụng

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

Điều này sẽ in phần bù trong big_fileđó vị trí của nội dung small_file(ví dụ 0 nếu small_filekhớp ở đầu big_file). Nếu small_filekhông khớp bên trong big_filethì sẽ không có gì được in. Nếu có lỗi, trạng thái thoát sẽ khác không.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.