Saya punya file besar A (terdiri dari email), satu baris untuk setiap email. Saya juga punya file B lain yang berisi set surat lain.
Perintah mana yang akan saya gunakan untuk menghapus semua alamat yang muncul dalam file B dari file A.
Jadi, jika file A mengandung:
A
B
C
dan file B berisi:
B
D
E
Maka file A harus dibiarkan dengan:
A
C
Sekarang saya tahu ini adalah pertanyaan yang mungkin lebih sering ditanyakan, tetapi saya hanya menemukan satu perintah online yang memberi saya kesalahan dengan pembatas yang buruk.
Bantuan apa pun akan sangat dihargai! Seseorang pasti akan datang dengan satu kalimat cerdas, tapi saya bukan ahli shell.
Jawaban:
Jika file diurutkan (ada dalam contoh Anda):
-23
menekan garis yang ada di kedua file, atau hanya di file 2. Jika file tidak diurutkan, pipa merekasort
terlebih dahulu ...Lihat halaman manual di sini
sumber
comm -23 file1 file2 > file3
akan menampilkan konten di file1 bukan di file2, ke file3. Danmv file3 file1
akhirnya akan menghapus konten yang berlebihan di file1.comm -23 file1 file2 | sponge file1
. Tidak diperlukan pembersihan.grep -Fvxf <lines-to-remove> <all-lines>
Contoh:
Keluaran:
Penjelasan:
-F
: gunakan string literal alih-alih BRE default-x
: hanya pertimbangkan kecocokan yang cocok dengan seluruh baris-v
: cetak tidak cocok-f file
: ambil pola dari file yang diberikanMetode ini lebih lambat pada file yang diurutkan sebelum metode lain, karena lebih umum. Jika kecepatan juga penting, lihat: Cara cepat menemukan baris dalam satu file yang tidak ada di file lain?
Berikut adalah otomatisasi bash cepat untuk operasi in-line:
GitHub hulu .
pemakaian:
Lihat juga: /unix/28158/is-there-a-tool-to-get-the-lines-in-one-file-that-are-not-in-another
sumber
awk untuk menyelamatkan!
Solusi ini tidak memerlukan input yang diurutkan. Anda harus menyediakan fileB terlebih dahulu.
kembali
Bagaimana cara kerjanya?
Perhatikan bahwa ini sekarang dapat digunakan untuk menghapus kata-kata daftar hitam.
dengan sedikit perubahan dapat membersihkan banyak daftar dan membuat versi yang sudah dibersihkan.
sumber
A\nC
, menulis ke file temp terlebih dahulu dan menimpa file asli... > tmp && mv tmp fileA
fileB
tidak kosong (panjang 0 byte), karena jika demikian, Anda akan mendapatkan hasil kosong alih-alih konten yang diharapkanfileA
. (Penyebab:FNR==NR
akan berlaku untukfileA
saat itu.)Cara lain untuk melakukan hal yang sama (juga membutuhkan input yang diurutkan):
Di Bash, jika file tidak disortir:
sumber
Anda dapat melakukan ini kecuali file Anda diurutkan
--new-line-format
adalah untuk baris yang ada di file b tetapi tidak di--old-..
is untuk baris yang ada di file a tetapi tidak di b--unchanged-..
adalah untuk baris yang ada di keduanya.%L
membuatnya jadi garis dicetak persis.untuk lebih jelasnya
sumber
comm
perintah.comm
membutuhkan file untuk diurutkan, jadi jika mereka diurutkan Anda dapat menggunakan solusi itu juga. Anda dapat menggunakan solusi ini terlepas dari apakah file diurutkan atau tidakPenyempurnaan dari jawaban bagus @ karakfa ini mungkin terasa lebih cepat untuk file yang sangat besar. Seperti dengan jawaban itu, file tidak perlu diurutkan, tetapi kecepatan terjamin berdasarkan array asosiatif awk. Hanya file pencarian yang disimpan dalam memori.
Formulasi ini juga memungkinkan untuk kemungkinan bahwa hanya satu bidang tertentu ($ N) dalam file input yang akan digunakan dalam perbandingan.
(Keuntungan lain dari pendekatan ini adalah mudah untuk memodifikasi kriteria perbandingan, misalnya untuk memangkas ruang putih terdepan dan tertinggal.)
sumber
Anda dapat menggunakan Python:
sumber
Kamu bisa memakai -
diff fileA fileB | grep "^>" | cut -c3- > fileA
Ini akan berfungsi untuk file yang tidak diurutkan juga.
sumber
Untuk menghapus garis umum antara dua file, Anda dapat menggunakan perintah grep, comm atau join.
Ini menampilkan baris dari file1 yang tidak cocok dengan baris apa pun di file2.
Ini menampilkan baris dari file1 yang tidak cocok dengan baris apa pun di file2.
sumber