Unione di duplicati parziali


2

Ho un file CSV con quattro colonne come questa

aa,bb,cc,dd  
ee,bb,cc,dd  
ff,bb,cc,dd  
xx,11,22,33  
yy,11,22,33  

Vorrei trasformarlo in:

aa,ee,ff,bb,cc,dd  
xx,yy,11,22,33  

Fondamentalmente, trova le linee in cui le ultime 3 colonne sono identiche e unisci il primo campo.

Qualcuno sa come farlo in bash o Python?

Risposte:


3

Perl

l'hash %hcontiene i dati mentre l'array @hgestisce l'ordine in cui sono stati rilevati gli elementi hash. OTW, le chiavi hash saranno selezionate in ordine casuale.

perl -F, -lane '
   BEGIN{ $"=$,=","; }
     push @{$h{"@F[-3..-1]"}}, $F[0];
     $h[-1+keys %h] = "@F[-3..-1]";
   END{ print  @{$h{$_}}, $_ for @h; }
'  yourcsvfile

Sed

sed -e '
   :loop
      $!N
      s/^\(.*\)\(\(,[^,]*\)\{3\}\)\n\([^,]*\)\2$/\1,\4\2/
   tloop
   P;D
'  yourcsvfile

bash

sed \$G yourcsvfile | # we add a dummy line to signal last record has been processed
while IFS=, read -r -a A; do
   var=${A[@]: -3:3}
   var=${var// /,}
   case $var in
      "$prev" ) x=${x-}${x:+,}${A[0]} ;;
      * ) case $prev in ?* ) echo "$x,$prev" ;; esac; prev=$var; x=${A[0]} ;;
   esac
done

4

Ecco un awkprogramma per questo:

#!/bin/awk -f
BEGIN {OFS = FS = ","}
{
    gsub(/ +$/, "", $4)
    field = $2","$3","$4
    if (field in a)
        a[field] = a[field]","$1
    else
        a[field] = $1
}
END { for (i in a) print a[i], i}

E il programma bonus python:

from collections import OrderedDict

records = OrderedDict()
for line in open('file1'):
    field, key = line.strip().split(',', 1)
    records.setdefault(key, []).append(field)
for key, fields in records.items():
    print(','.join(fields + [key]))

risultato:

aa,ee,ff,bb,cc,dd
xx,yy,11,22,33

Grazie mille! Sembra funzionare tranne per il fatto che il mio testo non ASCII appare strano nello stdout. Inoltre, in realtà il mio formato è CSV ... Ho provato a cambiare il delimitatore ma lo stdout sembra ancora strano.
Betotonbo,

Bene, se non conosciamo il formato, è un po 'più difficile farlo funzionare. Python può rendere breve il lavoro di CSV, ma ciò che alcuni considerano CSV copre molte variazioni.
Stephen Rauch,

Cambia lo spazio in ,. Sei sicuro di non averne bisogno ;?
Stephen Rauch,

Ho provato a dare un voto, ma non ci sono riuscito perché sono ancora nuovo. Quando ho provato il programma awk, ho ottenuto questo: xx, yy, 11,22,33 aa, bb, cc, dd ee, ff, bb, cc, dd - quindi quando ci sono più di due duplicati parziali, l'unione vale solo per due.
Betotonbo,

I tuoi dati hanno spazi finali. Ho appena aggiornato Awk per rimuovere gli spazi finali. Il pitone lo fa già.
Stephen Rauch,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.