Bandingkan dua file dengan kolom pertama dan hapus baris duplikat dari file ke-2 di skrip shell


9

Saya akan menanyakan pertanyaan saya dengan sebuah contoh. Saya punya 2 file:

File # 1:

118D FC300_R5_TP  FX.B      32775       2112   6       2038   6       2112   0
118E FC300_R5_TP  FX.B      32775       2136   7       2065   6       2136   0
118F FC300_R5_TP  FX.B      32775       2124   6       2064   6       2124   0
1190 FC300_R5_TP  FX.B     819210     814632  99     814609  99     814632   0
1191 FC300_R5_TP  FX.B     819210     104100  13     103714  13     104100   0
1192 FC300_R5_TP  FX.B    1638420    1609476  98    1609402  98    1609476   0
1196 FC300_R5_TP  FX.B    1638420    1638432 100    1638379 100    1638432   0
119A FC300_R5_TP  FX.B    3276840    3271776 100    3271698 100    3271776   0
119E FC300_R5_TP  FX.B    3276840    3264120 100    3264034 100    3264120   0
11A2 FC300_R5_TP  FX.B    3276840    2328648  71    2328546  71    2328648   0
11A6 FC300_R5_TP  FX.B    3276840    2328444  71    2328355  71    2328444   0
11AA FC300_R5_TP  FX.B    3276840    2328528  71    2328403  71    2328528   0
11AE FC300_R5_TP  FX.B    3276840    2328648  71    2328468  71    2328648   0
11B2 FC300_R5_TP  FX.B    3276840    2130000  65    2129766  65    2130000   0
173A FC300_R5_TP  FX.B    6553680    6478572  99    6477747  99    6478572   0

File # 2:

11AA FC300_R5_TP  FX.B    3276840    2328528  71    2328403  71    2328528   0
11AE FC300_R5_TP  FX.B    3276840    2328648  71    2328468  71    2328648   0
11B2 FC300_R5_TP  FX.B    3276840    2130000  65    2129766  65    2130000   0
173A FC300_R5_TP  FX.B    6553680    6478572  99    6477747  99    6478572   0
0BDB FC600_R5_TP  FX.B   33554640    6044364  18    6033105  18    6044364   0
0BDC FC600_R5_TP  FX.B   33554640    6613536  20    6481974  19    6613536   0
0BDD FC600_R5_TP  FX.B   33554640    4435848  13    4057170  12    4435848   0
0BDE FC600_R5_TP  FX.B   33554640    6620868  20    6249518  19    6620868   0

Output yang Diinginkan

File # 3:

0BDB FC600_R5_TP  FX.B   33554640    6044364  18    6033105  18    6044364   0
0BDC FC600_R5_TP  FX.B   33554640    6613536  20    6481974  19    6613536   0
0BDD FC600_R5_TP  FX.B   33554640    4435848  13    4057170  12    4435848   0
0BDE FC600_R5_TP  FX.B   33554640    6620868  20    6249518  19    6620868   0

Saya ingin membandingkan file 1 dan file 2 menggunakan kolom pertama mereka dan menghapus seluruh baris atau baris dari file 2 di mana mereka cocok dengan file 1. Saya juga ingin menyimpan hasilnya ke file ke-3, file # 3.

Jawaban:


10

Anda dapat menggunakan awkini:

awk 'FNR==NR{a[$1];next};!($1 in a)' file1 file2 > file3

Penjelasan:

  • FNR == NR: Tes ini benar ketika jumlah catatan sama dengan jumlah catatan dalam file. Ini hanya berlaku untuk file pertama, untuk file kedua NRakan sama dengan jumlah baris file1 + FNR.

  • a[$1]: Buat indeks elemen array dari bidang pertama file1.

  • next: lewati ke catatan berikutnya sehingga tidak ada lagi pemrosesan yang dilakukan pada file1.

  • !($1 in a): Lihat apakah bidang pertama ($ 1) ada dalam array, yaitu dalam file1, dan cetak seluruh baris (ke file3).

Berdasarkan salah satu contoh dari wiki #awk .


Jawaban sempurna !!!
mtk

8
export LC_ALL=C
comm -13 <(sort f1) <(sort  f2)

Akan melaporkan garis yang hanya di f2.

export LC_ALL=C
join -v2 <(sort f1) <(sort f2)

Akan melaporkan baris f2bidang pertama yang tidak ditemukan sebagai bidang pertama di setiap baris f1.

(Anda memerlukan shell dengan dukungan untuk substitusi proses seperti ksh93, zshatau bash).


2

Hanya untuk bersenang-senang, inilah solusi di Perl:

#!/usr/bin/perl

# create names lookup table from first file
my %names;
while (<>) {
    (my $col1)= split / /, $_;
    $names{$col1} = 1;
    last if eof;
}

# scan second file
while (<>) {
    print if /^(\S+).*/ && not $names{$1};
}

Contoh

$ ./showdiffs.pl file1  file2
0BDB FC600_R5_TP  FX.B   33554640    6044364  18    6033105  18    6044364   0
0BDC FC600_R5_TP  FX.B   33554640    6613536  20    6481974  19    6613536   0
0BDD FC600_R5_TP  FX.B   33554640    4435848  13    4057170  12    4435848   0
0BDE FC600_R5_TP  FX.B   33554640    6620868  20    6249518  19    6620868   0

Detail

Solusi Perl di atas terdiri dari 2 loop. Loop pertama membaca semua baris dari file1dan membuat hash, di %namesmana setiap kolom yang kami identifikasi ditambahkan.

$names{11AA} = 1;

whileLingkaran ke-2 kemudian berjalan di atas file ke-2 file2,, dan setiap kolom baris 1 diidentifikasi menggunakan ekspresi reguler:

^(\S+).*

Kata di atas mengatakan dari awal baris, cocokkan semua yang bukan spasi, dan simpan di variabel sementara $1. Itu disimpan dengan membungkus parens di sekitarnya. The .*mengatakan untuk mencocokkan segala sesuatu yang lain di telepon.

Bit berikutnya dari baris itu mengatakan untuk mencari kolom 1 bit yang baru saja kita simpan di $1dalam %nameshash:

$names{$1}

Jika ada di sana, maka kami tidak ingin mencetaknya. Jika tidak ada di sana, cetaklah.


2

Metode 1 # Bash

#!/usr/bin/env bash
file1=$1
file2=$2

[[ $# -ne 2 ]]  && { echo -e "\n\tUsage: \t$0 file1 file2\n"; exit 1; }

while read line
do

        if ! grep -q "${line%% .*}" $file1; then
                echo "${line}"
        fi

done < $file2

Metode 2 # Hanya Grep

grep -v "$(< file1)" file2

grep berfungsi, tetapi tidak menjamin


1

Mari kita dapatkan sebagai

File # 1: file1.txt

File # 2: file2.txt

Kemudian jalankan mengikuti di terminal

fgrep -vf test1.txt test2.txt > output.txt

output.txt akan berisi hasil yang diinginkan.

Penjelasan:

fgrep : print lines matching a pattern (from manual page)
-v  : get only non-matching rows
-f : obtain PATTERN from FILE (from manual page)

Ini hanya berfungsi jika seluruh baris identik, tetapi si penanya secara eksplisit meminta perbandingan hanya pada kolom pertama.
Adaephon
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.