Apakah ada alat yang bisa mendapatkan baris yang berisi file A, tetapi file B tidak? Saya dapat membuat skrip sederhana dengan, misalnya, perl, tetapi jika sesuatu seperti itu sudah ada, saya akan menghemat waktu saya sekarang.
Apakah ada alat yang bisa mendapatkan baris yang berisi file A, tetapi file B tidak? Saya dapat membuat skrip sederhana dengan, misalnya, perl, tetapi jika sesuatu seperti itu sudah ada, saya akan menghemat waktu saya sekarang.
Jawaban:
Iya. Alat standar grep
untuk mencari file untuk string teks dapat digunakan untuk mengurangi semua baris dalam satu file dari yang lain.
grep -F -x -v -f fileB fileA
Ini bekerja dengan menggunakan setiap baris dalam fileB sebagai pola ( -f fileB
) dan memperlakukannya sebagai string polos untuk mencocokkan (bukan regex biasa) ( -F
). Anda memaksa kecocokan terjadi pada seluruh baris ( -x
) dan mencetak hanya garis yang tidak cocok ( -v
). Karenanya Anda mencetak baris dalam fileA yang tidak berisi data yang sama dengan baris apa pun di fileB.
Kelemahan dari solusi ini adalah tidak memperhitungkan urutan baris dan jika input Anda memiliki garis duplikat di tempat yang berbeda, Anda mungkin tidak mendapatkan apa yang Anda harapkan. Solusi untuk itu adalah dengan menggunakan alat perbandingan nyata seperti diff
. Anda bisa melakukan ini dengan membuat file diff dengan nilai konteks pada 100% dari baris dalam file, kemudian menguraikannya hanya untuk baris yang akan dihapus jika mengkonversi file A ke file B. (Perhatikan perintah ini juga menghapus memformat setelah mendapat garis yang benar.)
diff -U $(wc -l < fileA) fileA fileB | sed -n 's/^-//p' > fileC
-u
Argumen huruf kecil sebenarnya mengambil parameter angka asalkan tidak diikuti oleh spasi. Keuntungan dari cara saya sebelumnya adalah bahwa ia akan bekerja dengan atau tanpa nilai, sehingga Anda dapat menggunakan sesuatu dalam rutinitas sub-perintah yang mengembalikan bukan output. Huruf besar '-U' di sisi lain membutuhkan argumen.
diff
pipa bekerja yang memperlakukan terima kasih.
grep
diperlukan. Contoh:grep -F -x -v -f <(sort fileB) <(sort fileA)
diff
adalah bahwa posisi dalam file diperhitungkan.
Jawabannya sangat tergantung pada jenis dan format file yang Anda bandingkan.
Jika file yang Anda bandingkan adalah file teks yang diurutkan, maka alat GNU yang ditulis oleh Richard Stallman dan Davide McKenzie disebut comm
dapat melakukan penyaringan yang Anda cari. Itu adalah bagian dari coreutils.
Katakanlah Anda memiliki 2 file berikut:
$ cat a
1
2
3
4
5
$ cat b
1
2
3
4
5
6
Baris dalam file b
yang tidak ada dalam file a
:
$ comm <(sort a) <(sort b) -3
6
comm
; sayangnya, comm
memerlukan file yang diurutkan
<()
? Ini berhasil dan saya mengerti, tetapi apakah ada nama untuk keanehan ini?
<()
juga dikenal sebagai proses substitusi .
comm
awalnya ditulis sekitar tahun 1973 oleh seseorang di Bell Labs, bukan rms. Anda merujuk pada implementasi GNU yang datang jauh kemudian. Ada banyak implementasi berbeda dari utilitas Unix sepanjang tahun.
dari stackoverflow ...
comm -23 file1 file2
-23 menekan garis yang ada di kedua file, atau hanya di file 2. File harus diurutkan (mereka ada dalam contoh Anda) tetapi jika tidak, pipa mereka melalui sortir terlebih dahulu ...
Lihat halaman manual di sini
Metode grep dan comm (dengan sortir) membutuhkan waktu lama pada file besar. SiegeX dan ghostdog74 membagikan dua metode awk yang hebat untuk mengekstraksi baris yang unik ke salah satu dari dua file di Stack Overflow:
$ awk 'FNR==NR{a[$0]++}FNR!=NR && !a[$0]{print}' file1 file2
$ awk 'FNR==NR{a[$0]++;next}(!($0 in a))' file1 file2
Jika file berukuran besar dan Anda tidak memiliki pesanan khusus untuk entri Anda, grep membutuhkan waktu terlalu lama. Alternatif cepat adalah
sort file1 > 1
sort file2 > 2
diff 1 2 | grep "\>" | sed -e 's/> //'
[hasil file2-file1 ke layar, pipa ke file dll]
Mengubah >
ke <
akan mendapatkan pengurangan yang berlawanan.rm 1 2