2017-10-17 33 views
3

J'ai un fichier texte dont le contenu peut être en double. Voici une représentation simplifiée de mon fichier txt. text signifie un caractère unique ou un mot ou une phrase). Notez que le séparateur ---------- peut ne pas être présent. En outre, tout le contenu du fichier se compose de caractères japonais et chinois unicode.Comment conserver la dernière occurrence de lignes dupliquées dans un fichier texte?

ÉDITÉ

sometext1 
sometext2 
sometext3 
aaaa 
sometext4 
aaaa 
aaaa 
bbbb 
bbbb 
cccc 
dddd 
eeee 
ffff 
gggg 
---------- 
sometext5 
eeee 
ffff 
gggg 
sometext6 
sometext7:cccc 
sometext8:dddd 
sometext9 
sometext10 

Ce que je veux atteindre est de ne conserver que la ligne avec la dernière occurrence des doublons comme ceci:

sometext1 
sometext2 
sometext3 
sometext4 
aaaa 
bbbb 
sometext5 
eeee 
ffff 
gggg 
sometext6 
sometext7:cccc 
sometext8:dddd 
sometext9 
sometext10 

Le plus proche que je trouve en ligne est How to remove only the first occurrence of a line in a file using sed mais cela nécessite que vous connaissez le (s) motif (s) à supprimer. Les sujets suggérés fournis lors de l'écriture du titre donnent Duplicating characters using sed et last occurence of date mais ils ne fonctionnaient pas.

Je suis sur un Mac avec Sierra. J'écris mes commandes exécutables dans un fichier script.sh pour exécuter les commandes ligne par ligne. J'utilise sed et gsed comme mes éditeurs de flux primaires.

+7

Comment définissez-vous 'duplicates'? – Kent

+4

Votre exemple n'est pas clair. Veuillez expliquer comment vous voyez votre mappage d'entrée sur cette sortie. – randomir

+1

Pourquoi ccc et ddd ont-ils disparu? – 123

Répondre

-1

Cela pourrait fonctionner pour vous (GNU sed):

sed -r '1h;1!H;x;s/([^\n]+)\n(.*\1)$/\2/;s/\n-+$//;x;$!d;x' file 

magasin la première ligne dans l'espace de maintien (HS) et ajouter toutes les lignes suivantes. Échangez vers le HS et supprimez toute ligne en double qui correspond à la dernière ligne. Supprimez également toutes les lignes de séparation, puis revenez à l'espace de modèle (PS). Supprimez tout sauf la dernière ligne, qui est permutée avec le HS et imprimée.

+0

Cela ne fonctionne pas. Donne une sortie brouillée. – codeforester

1

Je ne suis pas sûr si votre intention est de préserver l'ordre original des lignes. Si tel est le cas, vous pouvez le faire:

export LC_ALL=en_US.utf8 # to handle unicode characters in file 
nl -n rz -ba file | sort -k2,2 -t$'\t' | uniq -f1 | sort -k1,1 | cut -f2 
  • nl -n rz -ba file ajoute zéro les numéros de ligne rembourrés au fichier
  • sort -k2,2 -t'$\t' trie la sortie de nl par le second champ (notez que nl met un onglet après le numéro de ligne)
  • uniq -f1 supprime les doublons, tout en ignorant le champ numéro de ligne (-f1)
  • la sort finale rétablit la Origina l 'ordre des lignes, avec les doublons supprimés
  • cut -f2 supprime le champ de numéro de ligne, la restauration du contenu au format original
+1

Je ne dis pas que c'est * faux * puisque je pense que l'exemple donné est ambigu. Cependant, ceci est sensiblement différent de l'exemple donné ... L'OP doit clarifier ce qui est la sortie désirée et le raisonnement pour donner une réponse correcte. – dawg

+1

Et c'est aussi une jolie décoration, sorte, pipe non décorée btw. – dawg

+0

@codeforester C'est génial! Facile à comprendre en lisant les pages de manuel. L'ajout des numéros de ligne principaux est cool. J'ai été capable de supprimer les lignes dupliquées (c'est-à-dire exactement les mêmes, par exemple seulement 'sometext7: cccc' et' sometext7: cccc') en utilisant cette méthode. Mais cela ne fonctionnera pas dans ce cas, à savoir. Line10 'cccc' et Line21' sometext7: cccc', le 'cccc' est répété dans une partie d'une autre ligne. 'cccc' devrait être supprimé et' sometext7: cccc' conservé. Mais merci de signaler nl, trier et uniq pour moi! – Char

0

Ce awk est très proche.

Étant donné:

$ cat file 
sometext1 
sometext2 
sometext3 
aaaa 
sometext4 
aaaa 
aaaa 
bbbb 
bbbb 
cccc 
dddd 
eeee 
ffff 
gggg 
---------- 
sometext5 
eeee 
ffff 
gggg 
sometext6 
sometext7:cccc 
sometext8:dddd 
sometext9 
sometext10 

Vous pouvez faire:

$ awk 'BEGIN{FS=":"} 
     FNR==NR {for (i=1; i<=NF; i++) {dup[$i]++; last[$i]=NR;} next} 
     /^$/ {next} 
     {for (i=1; i<=NF; i++) 
      if (dup[$i] && FNR==last[$i]) {print $0; next}} 
     ' file file 
sometext1 
sometext2 
sometext3 
sometext4 
aaaa 
bbbb 
---------- 
sometext5 
eeee 
ffff 
gggg 
sometext6 
sometext7:cccc 
sometext8:dddd 
sometext9 
sometext10