Dosya1 ile dosya2'yi karşılaştırmak ve dosya1'de dosya2'de bulunmayan satırları içeren bir dosya3 oluşturmak istiyorum.
Dosya1 ile dosya2'yi karşılaştırmak ve dosya1'de dosya2'de bulunmayan satırları içeren bir dosya3 oluşturmak istiyorum.
Yanıtlar:
diff (1) cevap değil, ama comm (1) cevap.
NAME
comm - compare two sorted files line by line
SYNOPSIS
comm [OPTION]... FILE1 FILE2
...
-1 suppress lines unique to FILE1
-2 suppress lines unique to FILE2
-3 suppress lines that appear in both files
Yani
comm -2 -3 file1 file2 > file3
Girdi dosyaları sıralanmalıdır. Değilse, önce sıralayın. Bu geçici bir dosya ile yapılabilir veya ...
comm -2 -3 <(sort file1) <(sort file2) > file3
kabuğunuzun süreç ikamesini desteklemesi koşuluyla (bash yapar).
comm -23
Unix yardımcı programı diff
tam olarak bu amaç içindir.
$ diff -u file1 file2 > file3
Seçenekler, farklı çıktı biçimleri vb. İçin kılavuza ve İnternet'e bakın.
Şunu düşünün: a.txt dosyası:
abcd
efgh
b.txt dosyası:
abcd
Farkı şununla bulabilirsiniz:
diff -a --suppress-common-lines -y a.txt b.txt
Çıktı şu şekilde olacaktır:
efgh
Aşağıdakileri kullanarak çıktıyı bir çıktı dosyasında (c.txt) yeniden yönlendirebilirsiniz:
diff -a --suppress-common-lines -y a.txt b.txt > c.txt
Bu, sorunuza cevap verecektir:
"... dosya1'deki dosya2'de bulunmayan satırları içeren."
-d
yapacak olan, kullanmak isteyeceksiniz diff
. -i
, -E
, -w
, -B
Ve --suppress-blank-empty
ayrıca her ne kadar her zaman değil, bazen yararlı olabilir. Kullanım durumunuza neyin uyduğunu bilmiyorsanız, diff --help
önce deneyin (bu genellikle bir komutun ne yapabileceğini bilmediğinizde iyi bir fikirdir).
Bazen diff
ihtiyacınız olan yardımcı programdır, ancak bazen join
daha uygundur. Dosyaların önceden sıralanması gerekir veya bash, ksh veya zsh gibi işlem değiştirmeyi destekleyen bir kabuk kullanıyorsanız, sıralamayı anında yapabilirsiniz.
join -v 1 <(sort file1) <(sort file2)
Deneyin
sdiff file1 file2
Genelde benim için çoğu durumda çok daha iyi çalışıyor. Satır sırası önemli değilse (örneğin bazı metin yapılandırma dosyaları) dosyaları önceden sıralamak isteyebilirsiniz.
Örneğin,
sdiff -w 185 file1.cfg file2.cfg
sdiff <(sort file1) <(sort file2)
)
Bunu coreutils ile çözmeniz gerekiyorsa, kabul edilen cevap iyidir:
comm -23 <(sort file1) <(sort file2) > file3
Ayrıca sıralama veya işlem ikamesi gerektirmeyen ve sonsuz akışları destekleyen sd (stream diff) de kullanabilirsiniz , örneğin:
cat file1 | sd 'cat file2' > file3
Muhtemelen bu örnek için pek bir fayda sağlamaz, ancak yine de düşünün; bazı durumlarda comm
ne grep -F
de kullanamazsınız diff
.
Burada , terminalde farklı akışlar hakkında yazdığım, sd'yi tanıtan bir blog yazısı var.
Zaten birçok cevap var, ancak hiçbiri mükemmel IMHO. Thanatos'un cevabı her satırda fazladan karakter bırakır ve Sorpigal'ın cevabı dosyaların sıralanmasını veya önceden sıralanmasını gerektirir ki bu her koşulda yeterli olmayabilir.
Farklı ve başka bir şey (hiçbir ekstra karakter, hiçbir yeniden sipariş) olan hatları almanın en iyi yolu bir kombinasyonudur düşünüyorum diff
, grep
ve awk
(veya benzeri).
Satırlar "<" içermiyorsa, kısa bir tek satırlık olabilir:
diff urls.txt* | grep "<" | sed 's/< //g'
ancak bu her "<" örneğini (küçüktür, boşluk) satırlardan kaldıracaktır, bu her zaman uygun değildir (örneğin kaynak kodu). En güvenli seçenek awk kullanmaktır:
diff urls.txt* | grep "<" | awk '{for (i=2; i<NF; i++) printf $i " "; print $NF}'
Bu tek satırlık, her iki dosyayı da farklılaştırır, daha sonra diff'in ed stili çıktısını filtreler ve ardından diff'in eklediği sondaki "<" öğesini kaldırır. Bu, satırlar bazı "<" içerse bile çalışır.
diff a1.txt a2.txt | grep '> ' | sed 's/> //' > a3.txt
Bu konudaki neredeyse tüm cevapları denedim ama hiçbiri tamamlanmadı. Yukarıdaki birkaç patikadan sonra benim için çalıştı. diff size fark verecektir ama bazı istenmeyen özel karakterlerle. gerçek fark çizgileri '>' ile başlar. bu yüzden bir sonraki adım grep satırlarının '>' ile başlaması ve ardından sed ile aynısının kaldırılması .
<
. Girdi dosyalarının sırasını değiştirirseniz bunu göreceksiniz. Bunu yapsanız bile grep
daha fazla sed kullanarak atlamak isteyeceksiniz : `diff a1 a2 | sed '/> / s ///' `` Bu yine de içeren >
veya <
doğru durumda olan satırları kesebilir ve yine de satır numaralarını açıklayan ekstra satırlar bırakır. Bu yaklaşımı denemek istiyorsa daha iyi bir yolu olacaktır: diff -C0 a1 a2 | sed -ne '/^[+-] /s/^..//p'
.
diff
Aşağıdaki çıktı biçimlendirmesiyle kullanabilirsiniz :
diff --old-line-format='' --unchanged-line-format='' file1 file2
--old-line-format=''
, dosya2'de satır farklıysa dosya1 için çıktıyı devre dışı bırakın.
--unchanged-line-format=''
, satırlar aynıysa çıktıyı devre dışı bırakın.
Tek veya çok sütunlu bir CSV dosyanız varsa, bu satır satır "diff" işlemlerini sqlite3 gömülü db kullanarak yapabilirsiniz. Python ile birlikte gelir, bu nedenle çoğu linux / mac'ta mevcut olmalıdır. Python yazmaya gerek kalmadan bash kabuğundaki sqlite3 komutlarını yazabilirsiniz.
echo "
.mode csv
.import a.csv atable
.import b.csv btable
create table result as select * from atable EXCEPT select * from btable;
.output result.csv
select * from result ;
.quit
" | sqlite3 temp.db
Not: sqlite3 komutlarının her biri için bir satırsonu olduğundan emin olun .
Nasıl çalışır
Belirli sütunlar üzerinde işlem yapmanız gerekiyorsa, sqlite3 veya herhangi bir db gitmenin yoludur.
Yerleşik fark ve iletişim araçlarını kullanarak birden çok GB dosyasında farklılaşmayı denedim. Sqlite, linux hizmetlerini bir mil geride bırakır.