Có hai tệp được gọi là "a.txt" và "b.txt" đều có danh sách các từ. Bây giờ tôi muốn kiểm tra những từ nào là thêm trong "a.txt" và không có trong "b.txt" .
Tôi cần một thuật toán hiệu quả vì tôi cần so sánh hai từ điển.
Có hai tệp được gọi là "a.txt" và "b.txt" đều có danh sách các từ. Bây giờ tôi muốn kiểm tra những từ nào là thêm trong "a.txt" và không có trong "b.txt" .
Tôi cần một thuật toán hiệu quả vì tôi cần so sánh hai từ điển.
Câu trả lời:
Nếu bạn đã cài đặt vim, hãy thử điều này:
vimdiff file1 file2
hoặc là
vim -d file1 file2
bạn sẽ thấy nó thật tuyệt vời
Sắp xếp chúng và sử dụng comm
:
comm -23 <(sort a.txt) <(sort b.txt)
comm
so sánh (sắp xếp) các tệp đầu vào và theo mặc định xuất ra ba cột: các dòng duy nhất cho a, các dòng duy nhất cho b và các dòng có trong cả hai. Bằng cách xác định -1
, -2
và / hoặc -3
bạn có thể ngăn chặn các đầu ra tương ứng. Do đó, comm -23 a b
chỉ liệt kê các mục duy nhất cho a. Tôi sử dụng <(...)
cú pháp để sắp xếp các tệp một cách nhanh chóng, nếu chúng đã được sắp xếp, bạn không cần điều này.
comm
hiệu quả hơn vì nó thực hiện công việc trong một lần chạy, mà không lưu trữ toàn bộ tệp trong bộ nhớ. Vì bạn đang sử dụng từ điển rất có thể đã được sắp xếp, bạn thậm chí không cần đến sort
chúng. grep -f file1 file2
Mặt khác, việc sử dụng sẽ tải toàn bộ file1
vào bộ nhớ và so sánh từng dòng file2
với tất cả các mục đó, sẽ kém hiệu quả hơn nhiều. Nó chủ yếu hữu ích cho nhỏ, chưa được sắp xếp -f file1
.
\n
nó cũng sẽ được đưa vào để so sánh.
Bạn có thể sử dụng diff
công cụ trong linux để so sánh hai tập tin. Bạn có thể sử dụng các tùy chọn định dạng --changed-group-format và --unchanged-group để lọc dữ liệu cần thiết.
Có thể sử dụng ba tùy chọn sau để chọn nhóm phù hợp cho từng tùy chọn:
'% <' nhận các dòng từ FILE1
'%>' nhận các dòng từ FILE2
'' (Chuỗi trống) để xóa các dòng từ cả hai tệp.
Ví dụ: diff --changed-group-format = "% <" --unchanged-group-format = "" file1.txt file2.txt
[root@vmoracle11 tmp]# cat file1.txt
test one
test two
test three
test four
test eight
[root@vmoracle11 tmp]# cat file2.txt
test one
test three
test nine
[root@vmoracle11 tmp]# diff --changed-group-format='%<' --unchanged-group-format='' file1.txt file2.txt
test two
test four
test eight
Nếu bạn thích kiểu đầu ra khác từ git diff
, bạn có thể sử dụng nó với --no-index
cờ để so sánh các tệp không có trong kho git:
git diff --no-index a.txt b.txt
Sử dụng một vài tệp với mỗi chuỗi khoảng 200k tên tệp, tôi đã điểm chuẩn (với time
lệnh tích hợp) phương pháp này so với một số câu trả lời khác ở đây:
git diff --no-index a.txt b.txt
# ~1.2s
comm -23 <(sort a.txt) <(sort b.txt)
# ~0.2s
diff a.txt b.txt
# ~2.6s
sdiff a.txt b.txt
# ~2.7s
vimdiff a.txt b.txt
# ~3.2s
comm
dường như là nhanh nhất cho đến nay, trong khi git diff --no-index
dường như là cách tiếp cận nhanh nhất cho đầu ra kiểu khác.
Cập nhật 2018-03-25 Bạn thực sự có thể bỏ qua --no-index
cờ trừ khi bạn ở trong kho git và muốn so sánh các tệp không bị theo dõi trong kho đó. Từ trang người đàn ông :
Hình thức này là để so sánh hai đường dẫn đã cho trên hệ thống tập tin. Bạn có thể bỏ qua tùy chọn --no-index khi chạy lệnh trong cây làm việc được điều khiển bởi Git và ít nhất một trong các đường dẫn bên ngoài cây làm việc hoặc khi chạy lệnh bên ngoài cây làm việc do Git điều khiển.
Bạn cũng có thể sử dụng: colordiff : Hiển thị đầu ra của diff với màu sắc.
Giới thiệu về vimdiff : Nó cho phép bạn so sánh các tệp qua SSH, ví dụ:
vimdiff /var/log/secure scp://192.168.1.25/var/log/secure
Trích xuất từ: http://www.sysadmit.com/2016/05/linux-diferencias-entre-dos-archivos.html
Ngoài ra, đừng quên về mcdiff - Trình xem khác biệt nội bộ của GNU Midnight Commander .
Ví dụ:
mcdiff file1 file2
Thưởng thức!
Sử dụng comm -13
(yêu cầu các tệp được sắp xếp) :
$ cat file1
one
two
three
$ cat file2
one
two
three
four
$ comm -13 <(sort file1) <(sort file2)
four
Đây là giải pháp của tôi cho việc này:
mkdir temp
mkdir results
cp /usr/share/dict/american-english ~/temp/american-english-dictionary
cp /usr/share/dict/british-english ~/temp/british-english-dictionary
cat ~/temp/american-english-dictionary | wc -l > ~/results/count-american-english-dictionary
cat ~/temp/british-english-dictionary | wc -l > ~/results/count-british-english-dictionary
grep -Fxf ~/temp/american-english-dictionary ~/temp/british-english-dictionary > ~/results/common-english
grep -Fxvf ~/results/common-english ~/temp/american-english-dictionary > ~/results/unique-american-english
grep -Fxvf ~/results/common-english ~/temp/british-english-dictionary > ~/results/unique-british-english
sdiff -s file1 file2
là hữu ích.
Sử dụng awk cho nó. Hồ sơ kiểm tra:
$ cat a.txt
one
two
three
four
four
$ cat b.txt
three
two
one
Awk:
$ awk '
NR==FNR { # process b.txt or the first file
seen[$0] # hash words to hash seen
next # next word in b.txt
} # process a.txt or all files after the first
!($0 in seen)' b.txt a.txt # if word is not hashed to seen, output it
Các bản sao được xuất ra:
four
four
Để tránh trùng lặp, hãy thêm từng từ mới gặp trong a.txt vào seen
hàm băm:
$ awk '
NR==FNR {
seen[$0]
next
}
!($0 in seen) { # if word is not hashed to seen
seen[$0] # hash unseen a.txt words to seen to avoid duplicates
print # and output it
}' b.txt a.txt
Đầu ra:
four
Nếu danh sách từ được phân tách bằng dấu phẩy, như:
$ cat a.txt
four,four,three,three,two,one
five,six
$ cat b.txt
one,two,three
bạn phải thực hiện thêm một vài vòng ( for
vòng lặp):
awk -F, ' # comma-separated input
NR==FNR {
for(i=1;i<=NF;i++) # loop all comma-separated fields
seen[$i]
next
}
{
for(i=1;i<=NF;i++)
if(!($i in seen)) {
seen[$i] # this time we buffer output (below):
buffer=buffer (buffer==""?"":",") $i
}
if(buffer!="") { # output unempty buffers after each record in a.txt
print buffer
buffer=""
}
}' b.txt a.txt
Đầu ra lần này:
four
five,six
diff a.txt b.txt
Không đủ?