มีสองไฟล์ที่เรียกว่า"a.txt"และ"b.txt"ทั้งสองมีรายการคำ ตอนนี้ผมต้องการที่จะตรวจสอบคำที่มีความพิเศษในการ"a.txt"และไม่ได้อยู่ใน"b.txt"
ฉันต้องการอัลกอริทึมที่มีประสิทธิภาพเพราะฉันต้องการเปรียบเทียบพจนานุกรมสองเล่ม
มีสองไฟล์ที่เรียกว่า"a.txt"และ"b.txt"ทั้งสองมีรายการคำ ตอนนี้ผมต้องการที่จะตรวจสอบคำที่มีความพิเศษในการ"a.txt"และไม่ได้อยู่ใน"b.txt"
ฉันต้องการอัลกอริทึมที่มีประสิทธิภาพเพราะฉันต้องการเปรียบเทียบพจนานุกรมสองเล่ม
คำตอบ:
หากคุณติดตั้งเป็นกลุ่มลองสิ่งนี้:
vimdiff file1 file2
หรือ
vim -d file1 file2
คุณจะพบว่ามันยอดเยี่ยม
จัดเรียงและใช้comm
:
comm -23 <(sort a.txt) <(sort b.txt)
comm
เปรียบเทียบ (เรียงลำดับ) ไฟล์อินพุตและโดยดีฟอลต์เอาต์พุตสามคอลัมน์: บรรทัดที่ไม่ซ้ำกับ a, บรรทัดที่ไม่ซ้ำกับ b และบรรทัดที่มีอยู่ในทั้งสอง โดยการระบุ-1
, -2
และ / หรือ-3
คุณสามารถระงับการส่งออกที่สอดคล้องกัน ดังนั้นcomm -23 a b
จะแสดงเฉพาะรายการที่ไม่ซ้ำกับ a ฉันใช้<(...)
ไวยากรณ์เพื่อเรียงลำดับไฟล์ในทันทีหากไฟล์เหล่านั้นถูกจัดเรียงแล้วคุณไม่ต้องการสิ่งนี้
comm
มีประสิทธิภาพมากขึ้นเพราะทำงานในการรันครั้งเดียวโดยไม่ต้องเก็บไฟล์ทั้งหมดไว้ในหน่วยความจำ เมื่อคุณใช้พจนานุกรมที่เรียงลำดับแล้วคุณไม่จำเป็นต้องใช้sort
มัน การใช้grep -f file1 file2
ในทางกลับกันจะโหลดทั้งfile1
ในหน่วยความจำและเปรียบเทียบในแต่ละบรรทัดfile2
ที่มีทั้งหมดของรายการเหล่านั้นซึ่งมีประสิทธิภาพมากน้อย -f file1
มันมีประโยชน์ส่วนใหญ่มีขนาดเล็กไม่ได้เรียงลำดับ
\n
จะรวมอยู่ในการเปรียบเทียบ
ลองsdiff
( man sdiff
)
sdiff -s file1 file2
คุณสามารถใช้diff
เครื่องมือใน linux เพื่อเปรียบเทียบสองไฟล์ คุณสามารถใช้--changed กลุ่มรูปแบบและ--unchanged กลุ่มรูปแบบตัวเลือกในการกรองข้อมูลที่จำเป็น
สามตัวเลือกต่อไปนี้สามารถใช้เพื่อเลือกกลุ่มที่เกี่ยวข้องสำหรับแต่ละตัวเลือก:
'% <' รับสายจาก FILE1
'%>' รับสายจาก FILE2
'' (สตริงว่าง) เพื่อลบบรรทัดออกจากไฟล์ทั้งสอง
เช่น: 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
หากคุณต้องการสไตล์เอาต์พุตที่ต่างจากgit diff
คุณสามารถใช้กับ--no-index
แฟล็กเพื่อเปรียบเทียบไฟล์ที่ไม่อยู่ในที่เก็บ git:
git diff --no-index a.txt b.txt
ด้วยการใช้ไฟล์สองสามไฟล์ที่มีสตริงชื่อไฟล์ประมาณ 200k ในแต่ละครั้งฉันเปรียบเทียบ (ด้วยtime
คำสั่งในตัว) วิธีนี้เทียบกับคำตอบอื่น ๆ ที่นี่:
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
ดูเหมือนจะเร็วที่สุดในขณะที่git diff --no-index
ดูเหมือนจะเป็นวิธีที่เร็วที่สุดสำหรับเอาท์พุตสไตล์
อัปเดต 2018-03-25คุณสามารถละเว้นการ--no-index
ตั้งค่าสถานะได้เว้นแต่ว่าคุณอยู่ในที่เก็บ git และต้องการเปรียบเทียบไฟล์ที่ไม่ได้ติดตามภายในที่เก็บข้อมูลนั้น จากหน้าคน :
แบบฟอร์มนี้คือการเปรียบเทียบสองเส้นทางที่กำหนดบนระบบไฟล์ คุณสามารถละเว้นตัวเลือก --no-index เมื่อเรียกใช้คำสั่งในแผนผังการทำงานที่ควบคุมโดย Git และอย่างน้อยหนึ่งเส้นทางชี้ไปที่ด้านนอกแผนผังการทำงานหรือเมื่อเรียกใช้คำสั่งภายนอกแผนผังการทำงานที่ควบคุมโดย Git
คุณยังสามารถใช้: colordiff : แสดงผลลัพธ์ของ diff ด้วยสี
เกี่ยวกับvimdiff : อนุญาตให้คุณเปรียบเทียบไฟล์ผ่าน SSH เช่น:
vimdiff /var/log/secure scp://192.168.1.25/var/log/secure
แยกจาก: http://www.sysadmit.com/2016/05/linux-diferencias-entre-dos-archivos.html
นอกจากนี้อย่าลืมเกี่ยวกับmcdiff - โปรแกรมดู diff ภายในของGNU Midnight Commanderบัญชาการเที่ยงคืน
ตัวอย่างเช่น:
mcdiff file1 file2
สนุก!
ใช้comm -13
(ต้องการไฟล์ที่เรียงลำดับ) :
$ cat file1
one
two
three
$ cat file2
one
two
three
four
$ comm -13 <(sort file1) <(sort file2)
four
นี่คือทางออกของฉันสำหรับสิ่งนี้:
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
มีประโยชน์
ใช้ awk สำหรับมัน ทดสอบไฟล์:
$ cat a.txt
one
two
three
four
four
$ cat b.txt
three
two
one
The 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
รายการที่ซ้ำกันจะถูกส่งออก:
four
four
หากต้องการหลีกเลี่ยงคำที่ซ้ำกันให้เพิ่มคำที่พบใหม่แต่ละคำใน a.txt เพื่อseen
แฮช:
$ 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
เอาท์พุท:
four
หากรายการคำคั่นด้วยเครื่องหมายจุลภาคเช่น:
$ cat a.txt
four,four,three,three,two,one
five,six
$ cat b.txt
one,two,three
คุณต้องทำสองรอบพิเศษ ( for
ลูป):
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
ส่งออกเวลานี้:
four
five,six
diff a.txt b.txt
ไม่พอ?