2017-04-23 5 views
-1

Grande question: Je veux une liste des combinaisons uniques entre deux champs dans une trame de données.awk supprimer les doublons en miroir de 2 colonnes

données Exemple:

A B 
C D 
E F 
B A 
C F 
E F 

Je voudrais être en mesure d'obtenir le résultat de 4 combinaisons uniques: AB, CD, EF et FC Depuis BA et et BA contiennent les mêmes composants, mais dans un ordre différent, je ne veux qu'une copie (il est une relation mutuelle si BA est la même chose que AB)

Tentative:

Jusqu'à présent, je ont essayé de tri et de garder les lignes uniques:

sort file | uniq 

mais bien sûr, qui produit 5 combinaisons:

A B 
C D 
E F 
B A 
C F 

Je ne sais pas comment aborder AB/BA étant considéré comme le même. Des suggestions sur la façon de faire cela?

+1

Est-ce que les données réelles ont seulement deux caractères ou peut être plus de deux? –

+0

@George désolé je n'ai pas spécifié - les données réelles sont des caractères multiples par colonne, mais James et Ed ont fourni des réponses qui fonctionnent pour plusieurs caractères – user4670961

+1

Je suggérerais d'inclure un exemple d'entrée multi-char/sortie attendue; est possible quelques solutions pour rompre avec plusieurs caractères ... –

Répondre

3

L'approche idiomatiques awk est de commander les pièces d'index:

$ awk '!seen[$1>$2 ? $1 FS $2 : $2 FS $1]++' file 
A B 
C D 
E F 
C F 
+0

Le stockage des données réelles dans le tableau est-il préférable à la simple conservation d'un index? Il me semble que 'awk '$ 1 FS $ 2 en vu {prochain} $ 2 FS $ 1 en vu {prochain} {vu [$ 1 FS $ 2]}' fichier 'serait plus facile sur la mémoire, même si c'est quelques caractères de plus code. – ghoti

+1

'seen' contiendra exactement les mêmes valeurs de toute façon, l'ensemble unique de paires $ 1, $ 2. Oh, je vois ce que vous dites - pas besoin de garder le compte. Ce sera une goutte dans l'océan et un peu plus de mémoire pour une efficacité légèrement meilleure. –

2

En awk:

$ awk '($1$2 in a){next}{a[$1$2];a[$2$1]}1' file 
A B 
C D 
E F 
C F 

Expliqué:

($1$2 in a) { next }  # if duplicate in hash, next record 
{ a[$1$2]; a[$2$1] } 1 # hash reverse also and output 

Il fonctionne pour les champs simples char. Si vous souhaitez l'utiliser pour des chaînes plus longues, ajoutez FS entre les champs, comme a[$1 FS $2] etc. (merci @ EdMorton).

+0

@ghoti comment c'est utile ou constructif de se moquer de moi? Je suis en train d'apprendre le codage et je m'efforce de poser des questions de manière organisée en suivant la structure décrite sur ce site. C'est la dernière étape d'un problème plus long sur lequel je travaille et qui consiste principalement à utiliser awk. Si vous n'avez rien de gentil à dire, s'il vous plaît gardez le pour vous! – user4670961

+2

@EdMorton True, true. –

+2

Avez-vous oublié un '||' dans votre solution juste avant 1? Vous l'avez inclus dans votre explication mais pas dans votre code. –

3

un autre awk magique

awk '!a[$1,$2] && !a[$2,$1]++' file