İlk sütunu kullanarak iki dosyayı karşılaştırın ve kabuk betiğindeki 2. dosyadan yinelenen satırı kaldırın


9

Sorumu bir örnekle soracağım. 2 dosyam var:

Dosya # 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

Dosya # 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

Istenilen çıktı

Dosya # 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

İlk sütunlarını kullanarak dosya 1 ve dosya 2'yi karşılaştırmak ve dosya 1'de eşleştikleri dosya 2'den tüm satırı veya satırı kaldırmak istiyorum. Ayrıca sonuçları 3. dosyaya, dosya # 3'e kaydetmek istiyorum.

Yanıtlar:


10

Bunun için kullanabilirsiniz awk:

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

Açıklama:

  • FNR == NR: Bu test, kayıt sayısı dosyadaki kayıt sayısına eşit olduğunda geçerlidir. Bu sadece ilk dosya için geçerlidir, çünkü ikinci dosya dosya 1 NR+ satır sayısına eşit olacaktır FNR.

  • a[$1]: Dosya1'in ilk alanının bir dizi öğesi dizini oluşturun.

  • next: dosya1 üzerinde daha fazla işlem yapılmaması için bir sonraki kayda atlayın.

  • !($1 in a): İlk alanın ($ 1) dizide, yani dosya1'de bulunup bulunmadığına bakın ve tüm satırı (dosya3'e) yazdırın.

#Awk wiki'deki örneklerden birine dayanarak .


Mükemmel cevap!!!
mtk

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

Yalnızca içinde bulunan satırları bildirir f2.

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

f2Herhangi bir satırında ilk alanı ilk alan olarak bulunmayan satırları rapor eder f1.

(Eğer gibi işlem ikame için destek bir kabuk gerekir ksh93, zshya da bash).


2

Sadece eğlence için Perl'de bir çözüm var:

#!/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};
}

Misal

$ ./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

ayrıntılar

Yukarıdaki Perl çözeltisi 2 döngüden oluşur. İlk döngü, içindeki tüm satırları okur file1ve %namestanımladığımız her sütunun eklendiği bir karma oluşturur .

$names{11AA} = 1;

Ardından 2. whiledöngü 2. dosyanın üzerinden geçer file2ve her satırın sütun 1'i normal ifade kullanılarak tanımlanır:

^(\S+).*

Yukarıdaki satırın başından itibaren, boşluk olmayan her şeyi eşleştirin ve geçici değişkene kaydedin $1. Parenleri etrafına sararak kurtarıldı. .*On line her şeyi eşleşecek şekilde söylüyor.

Bu çizgilerin sonraki bit sadece kayıtlı Sütun 1 bit bakmak için söylüyor $1yılında %nameskarma:

$names{$1}

Orada varsa, o zaman yazdırmak istemiyoruz. Orada değilse, yazdırın.


2

Yöntem 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

Yöntem 2 # Sadece Grep

grep -v "$(< file1)" file2

grep çalışıyor, ancak garanti değil


1

Gibi olsun

Dosya # 1: file1.txt

Dosya # 2: file2.txt

Sonra terminalde aşağıdakileri çalıştırın

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

output.txt istenen sonuçları içerecektir.

Açıklama:

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

Bu yalnızca tüm satırlar aynı ise çalışır, ancak sorgulayandan açıkça yalnızca ilk sütunda karşılaştırma istenir.
Adaephon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.