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.