Làm thế nào để biết nếu một tệp văn bản là một tập hợp con của một tập tin khác


12

Tôi đang cố gắng tìm cách xác định xem một tệp văn bản có phải là tập hợp con của một tệp khác không ..

Ví dụ:

foo
bar

là một tập hợp con của

foo
bar
pluto

Trong khi:

foo
pluto

foo
bar

không phải là một tập hợp con của nhau ...

Có cách nào để làm điều này với một lệnh?

Kiểm tra này phải là kiểm tra chéo và phải trả lại:

file1 subset of file2 :    True
file2 subset of file1 :    True
otherwise             :    False

Giải pháp hiệu quả tiềm năng hơn (nếu các tệp cũng được đặt hàng): github.com/barrycarter/bcapps/blob/master/ chủ
barrycarter 26/12/14

Câu trả lời:


11

Nếu những nội dung tập tin được gọi file1, file2file3theo thứ tự apearance sau đó bạn có thể làm điều đó với những điều sau một lót:

 # python -c "x=open('file1').read(); y=open('file2').read(); print x in y or y in x"
 True
 # python -c "x=open('file2').read(); y=open('file1').read(); print x in y or y in x"
 True
 # python -c "x=open('file1').read(); y=open('file3').read(); print x in y or y in x"
 False

Cảm ơn câu trả lời của bạn .. +1 .. Tôi không biết nếu chấp nhận câu trả lời của mình vì câu trả lời của bạn không phải là unix-linux và câu trả lời của tôi nhanh hơn một chút, theo như tôi đã kiểm tra nó .. bạn nghĩ sao?
gc5

Bạn hoan nghênh, tất nhiên có các giải pháp khác với các công cụ cụ thể hơn unix. Nhưng điều này có vẻ là một cách sử dụng tốt intoán tử của Python .
Timo

Có trình bao bọc dòng lệnh python để làm cho nó trở nên giống nhau hơn, với đường ống được tích hợp sẵn, được đặt tên là pyp: code.google.com/p/pyp Tôi nghĩ rằng nó là tầm thường để làm cho giải pháp này trở nên đơn giản hơn như một công cụ lót.
IBr

3

Với perl:

if perl -0777 -e '$n = <>; $h = <>; exit(index($h,$n)<0)' needle.txt haystack.txt
then echo needle.txt is found in haystack.txt
fi

-0octalxác định dấu phân cách bản ghi. Khi số bát phân đó lớn hơn 0377 (giá trị byte tối đa), điều đó có nghĩa là không có dấu phân cách, nó tương đương với việc thực hiện $/ = undef. Trong trường hợp đó, <>trả về toàn bộ nội dung của một tệp, đó là chế độ nhếch nhác .

Khi chúng tôi có nội dung của các tệp trong hai $h$nbiến, chúng tôi có thể sử dụng index()để xác định xem cái này có được tìm thấy trong cái kia không.

Tuy nhiên, điều đó có nghĩa là toàn bộ tệp được lưu trữ trong bộ nhớ, điều đó có nghĩa là phương thức đó sẽ không hoạt động đối với các tệp rất lớn.

Đối với các tệp mmappable (thường bao gồm các tệp thông thường và hầu hết các tệp có thể tìm kiếm như thiết bị khối), có thể được xử lý bằng cách sử dụng mmap()trên các tệp, như với Sys::Mmapmô-đun perl:

if 
  perl -MSys::Mmap -le '
    open N, "<", $ARGV[0] || die "$ARGV[0]: $!";
    open H, "<", $ARGV[1] || die "$ARGV[1]: $!";
    mmap($n, 0, PROT_READ, MAP_SHARED, N);
    mmap($h, 0, PROT_READ, MAP_SHARED, H);
    exit (index($h, $n) < 0)' needle.txt haystack.txt
then
  echo needle.txt is found in haystack.txt
fi

2

Tôi tìm thấy một giải pháp nhờ câu hỏi này

Về cơ bản tôi đang thử nghiệm hai tệp a.txtb.txtvới tập lệnh này:

#!/bin/bash

first_cmp=$(diff --unchanged-line-format= --old-line-format= --new-line-format='%L' "$1" "$2" | wc -l)
second_cmp=$(diff --unchanged-line-format= --old-line-format= --new-line-format='%L' "$2" "$1" | wc -l)

if [ "$first_cmp" -eq "0" -o "$second_cmp" -eq "0" ]
then
    echo "Subset"
    exit 0
else
    echo "Not subset"
    exit 1
fi

Nếu ai được tập hợp con của người kia sự trở lại kịch bản 0cho Truekhác 1.


% L làm gì? Kịch bản này dường như không hoạt động và tôi đang cố gắng gỡ lỗi nó ...
Alex

Tôi thực sự không nhớ ý nghĩa của %Lnó, đó là ba năm trước. Từ man diff(phiên bản hiện tại) %Lcó nghĩa là "nội dung của dòng".
gc5

% L in nội dung của dòng "mới". IOW, không in bất cứ thứ gì cho dòng không thay đổi hoặc dòng cũ, nhưng in nội dung của dòng cho dòng mới.
PLG

Kịch bản này làm việc cho tôi, ra khỏi hộp!
PLG

2

Nếu F1 là tập con của f2 thì F1 - f2 là tập rỗng. Dựa vào đó chúng ta có thể viết một hàm is_subset và một hàm xuất phát từ nó. Theo cài đặt chênh lệch giữa 2 tệp văn bản


sort_files () {
  F1_sort = "$ 1.sort"
  f2_sort = "$ 2.sort"

  nếu [ ! -f $ f1_sort]; sau đó
    mèo $ 1 | sắp xếp | uniq> $ f1_sort
  fi

  nếu [ ! -f $ f2_sort]; sau đó
    mèo $ 2 | sắp xếp | uniq> $ f2_sort
  fi
}

remove_sort_files () {
  F1_sort = "$ 1.sort"
  f2_sort = "$ 2.sort"
  rm -f $ f1_sort
  rm -f $ f2_sort
}

set_union () {
  sort_files $ 1 $ 2
  con mèo "$ 1.sort" "$ 2.sort" | sắp xếp | uniq
  remove_sort_files $ 1 $ 2
}

set_diff () {
  sort_files $ 1 $ 2
  con mèo "$ 1.sort" "$ 2.sort" "$ 2.sort" | sắp xếp | uniq -u
  remove_sort_files $ 1 $ 2
}

rset_diff () {
  sort_files $ 1 $ 2
  con mèo "$ 1.sort" "$ 2.sort" "$ 1.sort" | sắp xếp | uniq -u
  remove_sort_files $ 1 $ 2
}

is_subset () {
  sort_files $ 1 $ 2
  đầu ra = $ (set_diff $ 1 $ 2)
  remove_sort_files $ 1 $ 2

  nếu [-z $ đầu ra]; sau đó
    trả về 0
  khác
    trả lại 1
  fi

}


Kịch bản này có nên bắt đầu bằng #!/bin/bash?
Alex

2

Từ http://www.catonmat.net/blog/set-operations-in-unix-shell/ :

Comm so sánh hai tập tin được sắp xếp theo từng dòng. Nó có thể được chạy theo cách nó xuất ra các dòng chỉ xuất hiện trong tệp được chỉ định đầu tiên. Nếu tệp đầu tiên là tập con của tệp thứ hai, thì tất cả các dòng trong tệp thứ 1 cũng xuất hiện trong tệp thứ 2, do đó không có đầu ra nào được tạo ra:

$ comm -23 <(sort subset | uniq) <(sort set | uniq) | head -1
# comm returns no output if subset ⊆ set
# comm outputs something if subset ⊊ set
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.