GNU/Linux >> Linux Esercitazione >  >> Linux

Rimuovere i campi duplicati in una determinata colonna?

Vorrei rimuovere da una determinata colonna ($ 2 nell'esempio) i campi duplicati (separati da virgole).

File di input:

A    1,2,3,4   
B    4,5,6,3
C    2,15

Uscita prevista:

A    1,2,3,4
B    5,6
C    15

Risposta accettata:

perl -lpe 's/sKS+/join ",", grep {!$seen{$_}++} split ",", $&/e'

Puoi eseguire quanto sopra in questo modo:

$ perl -lpe 's/sKS+/join ",", grep {!$seen{$_}++} split ",", $&/e' afile 
A    1,2,3,4
B    5,6
C    15

Come funziona

Prima chiamata a perl con -lpe fa le seguenti 3 cose.

  • -l[octal] abilita l'elaborazione di fine riga, specifica il terminatore di riga
  • -p assume loop come -n ma stampa anche la riga, come sed
  • -e program una riga di programma (più -e consentite, omettere il file di programma)

Questo essenzialmente prende il file, rimuove le nuove righe, opera su una riga e quindi inserisce un carattere di nuova riga su di essa quando ha finito. Quindi è solo scorrere il file ed eseguire il nostro codice Perl contro ciascuno a turno.

Per quanto riguarda il codice Perl attuale:

  • s indica un carattere di spaziatura (i cinque caratteri [ fnrt] e v nelle versioni più recenti di perl , come [[:space:]] ).
  • K Mantieni il resto della K, non includerlo in $&
  • S+ uno o più caratteri non presenti nell'insieme [ fnrtv]

Il join ",", prenderà i risultati e si unirà nuovamente a ciascun campo in modo che sia separato da una virgola.

Il split ",", $& prenderà le corrispondenze che sono state trovate da S+ e suddividili nei soli campi, senza la virgola.

Il grep {!$seen{$_}++} prenderà il numero di ogni campo, lo aggiungerà all'hash, $seen{} dove il numero di ogni campo è $_ mentre esaminiamo ciascuno di essi. Ogni volta che un numero di campo viene "visto", viene contato tramite il ++ operatore, $seen{$_}++ .

Il grep{!$seen{$_}++} restituirà un valore di campo se è stato visto solo una volta.

Modificato per vedere cosa sta succedendo

Se usi questo abominio modificato puoi vedere cosa sta succedendo mentre questa battuta di Perl si sposta attraverso le linee del file.

$ perl -lpe 's/sKS+/join ",", grep {!$seen{$_}++} split ",", $&/e; @a=keys %seen; @b=values %seen; print "keys: @a | vals: @b"' afile 
keys: 4 1 3 2 | vals: 1 1 1 1
A    1,2,3,4
keys: 6 4 1 3 2 5 | vals: 1 2 1 2 1 1
B    5,6
keys: 6 4 1 3 2 15 5 | vals: 1 2 1 2 2 1 1
C    15

Questo ti mostra il contenuto di $seen{} al termine dell'elaborazione di una riga del file. Prendiamo la seconda riga del file.

B    4,5,6,3

Ed ecco come la mia versione modificata mostra quella riga come:

keys: 6 4 1 3 2 15 5 | vals: 1 2 1 2 2 1 1

Quindi questo significa che abbiamo visto il campo n. 6 (1 volta), il campo n. 4 (2 volte), ecc. e il campo n. 5 (1 volta). Quindi, quando grep{...} restituisce i risultati restituirà risultati da questo array solo se era presente in questa riga (4,5,6,3) e se l'abbiamo visto solo 1 volta (6,1,15,5). L'intersezione di questi 2 elenchi è (5,6) e quindi questo è ciò che viene restituito da grep .

Riferimenti

  • perlre – perldoc.perl.org
Correlati:modo per modificare un file sul posto?
Linux
  1. Come trovare e rimuovere le foto duplicate in Linux

  2. Rimuovere una chiave scaduta in APT

  3. Come rimuovere le righe duplicate all'interno di un file di testo?

  4. Rimuovere le righe in base ai duplicati all'interno di una colonna senza ordinare?

  5. Ordinare l'output per colonna?

Come rimuovere le righe duplicate in MySQL

Come trovare e rimuovere file duplicati/indesiderati in Linux utilizzando lo strumento "FSlint".

Scollega comando in Linux (Rimuovi file)

Come trovare file duplicati in Linux e rimuoverli

Come rimuovere le voci duplicate nel dialogo "aperto con" Nautilus?

Come posso rimuovere i file duplicati su alberi di directory separati?