Jika file diurutkan (ada dalam contoh Anda):
comm -23 file1 file2
-23
menekan baris yang ada di kedua file, atau hanya di file 2. Jika file tidak diurutkan, kirimkan melalui sort
pertama...
Lihat halaman manualnya di sini
awk untuk menyelamatkan!
Solusi ini tidak memerlukan input yang diurutkan. Anda harus menyediakan fileB terlebih dahulu.
awk 'NR==FNR{a[$0];next} !($0 in a)' fileB fileA
kembali
A
C
Bagaimana cara kerjanya?
NR==FNR{a[$0];next}
idiom adalah untuk menyimpan file pertama dalam larik asosiatif sebagai kunci untuk pengujian "berisi" selanjutnya.
NR==FNR
sedang memeriksa apakah kami memindai file pertama, dengan penghitung baris (NR) global sama dengan penghitung baris file (FNR) saat ini.
a[$0]
menambahkan baris saat ini ke array asosiatif sebagai kunci, perhatikan bahwa ini berperilaku seperti satu set, di mana tidak akan ada nilai duplikat (kunci)
!($0 in a)
kita sekarang berada di file berikutnya,in
adalah tes berisi, di sini memeriksa apakah baris saat ini ada di set yang kita isi di langkah pertama dari file pertama,!
meniadakan kondisi tersebut. Apa yang hilang di sini adalah tindakannya, yang secara default adalah{print}
dan biasanya tidak ditulis secara eksplisit.
Perhatikan bahwa ini sekarang dapat digunakan untuk menghapus kata-kata yang masuk daftar hitam.
$ awk '...' badwords allwords > goodwords
dengan sedikit perubahan dapat membersihkan beberapa daftar dan membuat versi yang dibersihkan.
$ awk 'NR==FNR{a[$0];next} !($0 in a){print > FILENAME".clean"}' bad file1 file2 file3 ...
Cara lain untuk melakukan hal yang sama (juga membutuhkan masukan yang diurutkan):
join -v 1 fileA fileB
Di Bash, jika file tidak diurutkan sebelumnya:
join -v 1 <(sort fileA) <(sort fileB)
grep -Fvxf <lines-to-remove> <all-lines>
- berfungsi pada file yang tidak diurutkan (tidak seperti
comm
) - menjaga ketertiban
- adalah POSIX
Contoh:
cat <<EOF > A
b
1
a
0
01
b
1
EOF
cat <<EOF > B
0
1
EOF
grep -Fvxf B A
Keluaran:
b
a
01
b
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 diberikan
Metode ini lebih lambat pada file yang sudah diurutkan sebelumnya daripada metode lain, karena lebih umum. Jika kecepatan juga penting, lihat:Cara cepat menemukan baris di satu file yang tidak ada di file lain?
Inilah otomatisasi bash cepat untuk operasi in-line:
remove-lines() (
remove_lines="$1"
all_lines="$2"
tmp_file="$(mktemp)"
grep -Fvxf "$remove_lines" "$all_lines" > "$tmp_file"
mv "$tmp_file" "$all_lines"
)
GitHub upstream.
penggunaan:
remove-lines lines-to-remove remove-from-this-file
Lihat juga:https://unix.stackexchange.com/questions/28158/is-there-a-tool-to-get-the-lines-in-one-file-that-are-not-in-another