başka bir sütunun değerine göre kopyaları kaldır


9

Aşağıdaki dosya var:

AA,true
AA,false
BB,false
CC,false
BB,true
DD,true

Yinelenenleri aramak ve sütun değeri eşit olan satırı kaldırmak çalışıyorum true.

çıktı olarak olması gerekir:

AA,false
BB,false
CC,false
DD,true

2
Yani .. sadece trueilk sütunun ilk örneğiyse sakla ?
DopeGhoti

1
@RomanPerekhrest Muhtemelen çünkü uniqi bir giriş ve "olduğu gibi" basılmıştır
George Vasiliou

@RomanPerekhrest çünkü DD, true yinelenmiyor, DD ile başka bir satırımız yok, false.
Hani Gotc

AA,true AA,false AA,false AA,falseBu durumda ne çıktı olmalı? Anlıyorum, bu satır yalnızca yinelenen ve trueaynı anda içeriyorsa kaldırılmalıdır . falseHer durumda tüm satırlara dokunulmamalıdır. Yani, bu durumda, sadece AA, truekaldırılacaktır. Ama bütün cevaplar sadece bir satır bırakıyor AA,false. Just interesting :)
MiniMax

Yanıtlar:


9
awk -F, '$2 == "false" {data[$1]=$2 } $2=="true" { if ( data[$1]!="false" ) { data[$1]=$2 } } END { OFS=","; for (item in data) { print item,data[item] }}' input

Komut dosyasını açıklama amacıyla dikey olarak genişletmek için:

BEGIN {
   FS=","         # Set the input separator; this is what -F, does.
}
$2 == "false" {    # For any line whose second field is "false", we
   data[$1]=$2     # will use that value no matter what.
}
$2=="true" {                    # For lines whose second field is "true",
   if ( data[$1]!="false" ) {   # only keep if if we haven't yet seen a
      data[$1]=$2               # "false"
   }
}
END {                           # Now that we have tabulated our data, we
   OFS=","                      # can print it out by iterating through 
   for (item in data) {         # the array we created.
      print item,data[item]
   }
}

@DopeGhoti iyi açıkladı! Bu konuda + 1'im var.
Valentin Bajrami

14

Basit sürüm:

sort input.txt | awk -F, '!a[$1]++'

"false" alfabetik olarak "true" dan önce sıralar ve buradaki Awk komutu ilk satırı yalnızca her farklı ilk alan değeri için tutar.

"False" yerine "true" yu tutmak istiyorsanız, tersine sıralayın, aynı Awk komutuna iletin ve daha sonra tekrar tersine sıralayın.


1
Ayrıca, -useçenek varsa ,sort input.txt | sort -t, -u -k1,1
Sundeep

2
@Sundeep neden iki sortçağrı kullanıyorsunuz? Neden sadece sort -ut, -k1,1 input.txt ?
terdon

2
@terdon çünkü -ugiriş dosyasında bulunan ilk satırı kopyalar arasında tutacaktır ... verilen durum için, giriş -uuygulanmadan önce sıralanmalıdır ... ex için: verilen örnekte ilk göründüğü için AA,trueyerine yazdırılacaktır AA,false.. awk -F, '!a[$1]++'Bu sorunu tek başına çözememesinin aynı nedeni
Sundeep

5
perl -F, -lane '
   exists $h{$F[0]} or $h[$h{$F[0]}=@h]=$_;
   $h=$_; /,false$/ or $_=$h for $h[$h{$F[0]}];
   END{ print for @h; }
' duplicates.file

Veri yapıları:

  • Hash %hAnahtarları ilk alanlar (AAA BBB, CCC, vb) ve karşılık gelen değerleri tuşları karşılaşıldı sırayı anlatan sayılardır. Böylece, örneğin, AAA => 0 tuşu, BBB => 1 tuşu, CCC => 2 tuşu.
  • @hÖğeleri baskı sırasında yer alan çizgiler olan dizi . Verilerde hem true hem de false bulunursa, false değeri diziye girer. OTW, bir tür veri varsa, o zaman bu mevcut olurdu.

Başka bir yol GNU sed kullanmaktır:

sed -Ee '
   G
   /^([^,]*),(false|true)\n(.*\n)?\1,\2(\n|$)/ba
   /^([^,]*)(,true)\n(.*\n)?\1,false(\n|$)/ba
   /^([^,]*)(,false)\n((.*\n)?)\1,true(\n|$)/{
      s//\3\1\2\5/;h;ba
   }
   s/([^\n]*)\n(.*)$/\2\n\1/;s/^\n*//
   h;:a;$!d;g
' duplicates.file

FWIW, yukarıdaki GNU-sed kodu için POSIX eşdeğer kodu aşağıda listelenmiştir:

sed -e '
   G

   /^\([^,]*\),\(false\)\n\(.*\n\)\{0,1\}\1,\2$/ba
   /^\([^,]*\),\(false\)\n\(.*\n\)\{0,1\}\1,\2\n/ba

   /^\([^,]*\),\(true\)\n\(.*\n\)\{0,1\}\1,\2$/ba
   /^\([^,]*\),\(true\)\n\(.*\n\)\{0,1\}\1,\2\n/ba

   /^\([^,]*\),true\n\(.*\n\)\{0,1\}\1,false$/ba
   /^\([^,]*\),true\n\(.*\n\)\{0,1\}\1,false\n/ba

   /^\([^,]*\)\(,false\)\n\(\(.*\n\)\{0,1\}\)\1,true$/{
      s//\3\1\2/
      h
      ba
   }
   /^\([^,]*\)\(,false\)\n\(\(.*\n\)\{0,1\}\)\1,true\n/{
      s//\3\1\2\n/
      h
      ba
   }

   y/\n_/_\n/
   s/\([^_]*\)_\(.*\)$/\2_\1/;s/^_*//
   y/\n_/_\n/

   h;:a;$!d;g
' duplicates.file

açıklama

  • Bu yöntemde nihayet yazdırılacak sonucu bekletme alanında saklarız.
  • Okunan her satır için, mevcut alanın mevcut tutma alanı karşısında incelenmesi için tutma alanını desen alanına ekleriz.
  • Şimdi bu karşılaştırma sırasında 5 şey olabilir:
    • a) Geçerli satır, bekletme satırındaki bir yerde eşleşir & false: false.
      • [ACTION] Aynı yanlış durum bulunduğundan, hiçbir şey yapmayın.
    • b) Geçerli satır, bekletme satırındaki bir yerde eşleşir & true: true.
      • [ACTION] Aynı gerçek durum bulunduğundan, hiçbir şey yapmayın.
    • c) Geçerli satır, bekletme satırındaki bir yerde eşleşiyor & true: false.
      • [EYLEM] Yanlış bir durum zaten mevcut olduğundan hiçbir şey yapmayın.
    • d) Geçerli satır, bekletme satırındaki bir yerde eşleşir & false: true.
      • [EYLEM] Bu, bazı çalışmayı içerir, çünkü yanlış satırı, doğrunun bulunduğu konumla aynı konumda değiştirmemiz gerekir.
    • e) Geçerli hat, bekletme hattının hiçbir yerinde eşleşmiyor.
      • [EYLEM] Mevcut satırı sonuna kadar taşıyın.

Sonuçlar

AA,false
BB,false
CC,false
DD,true

3

Her giriş satırı için, SADECE o anahtarın değerini henüz kaydetmediysek , ikinci alanın değerini ilişkilendirilebilir dizide a(dizinin anahtarı olarak ilk alanı kullanarak) saklayın . Hem giriş hem de çıkış alanı ayırıcısı için kullanın . Tüm giriş satırlarını okuduktan sonra diziyi yazdırın.false,

$ awk -F, -v OFS=, 'a[$1] != "false" { a[$1] = $2 };
                    END { for (i in a) {print i,a[i]} }' truefalse.txt
AA,false
BB,false
CC,false
DD,true

Bu ve DopeGhoti'nin sürümü arasındaki önemli fark, bu sürümün değeri hakkında hiç umursamaması, $2sadece varsa değerini önemsiyor olmasıdır a[$1].


1

İki geçişli sortçözüm

sort -k1,1 -k2,2 -t, file | sort -k1,1 -t, -u

Birinci sortalan tarafından kümeleri kayıtları geçmesi 1ile falseönceki kayıtlar trueortak bir alan dövme kayıtların her blok için 1bir değer. İkinci sortgeçiş, alanın 1izniyle her bir ayrı değer için bir kayıt verecek şekilde ayarlanır -u. Yana -usabit tür anlamına gelir, bu şekilde elde bir kayıt alanı içindeki her ayrı değeri için karşılaşılan ilk kayıttır 1bir kayıt olduğunu - falsenedeniyle, ilk olarak yapılan iş için ikinci alana sortgeçiş

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.