Question

Pour utiliser la commande uniq, vous devez d'abord trier votre fichier.

Mais dans le fichier que j'ai, l'ordre des informations est important. Comment puis-je conserver le format d'origine du fichier tout en supprimant le contenu dupliqué?

Était-ce utile?

La solution

Une autre version d'awk:

awk '!_[<*>]++' infile

Autres conseils

Ce awk conserve la première occurrence. Même algorithme que les autres réponses utilisent:

awk '!(
sort file | uniq -d | awk '
   FNR == NR { dups[<*>] }
   FNR != NR && (!(<*> in dups) || !lines[<*>]++)
' - file
in lines) { print <*>; lines[<*>]; }'

En voici un qui n'a besoin que de stocker les lignes dupliquées (par opposition à toutes les lignes) en utilisant awk :

<*>

Il existe également le "numéro de ligne, tri double". méthode.

 nl -n ln | sort -u -k 2| sort -k 1n | cut -f 2-

Vous pouvez exécuter uniq -d sur la version triée du fichier pour rechercher les lignes en double, puis exécuter un script indiquant:

if this_line is in duplicate_lines {
    if not i_have_seen[this_line] {
        output this_line
        i_have_seen[this_line] = true
    }
} else {
    output this_line
}

Utiliser uniquement uniq et grep:

Créer un fichier dsh:

#!/bin/sh
sort $1 | uniq > $1_uniq
for line in $(cat $1); do
cat $1_uniq | grep -m1 $line >> $1_out
cat $1_uniq | grep -v $line > $1_uniq2
mv $1_uniq2 $1_uniq
done;
rm $1_uniq

Exemple:

./d.sh infile

Vous pouvez utiliser une horrible chose O (n ^ 2), comme ceci (pseudo-code):

file2 = EMPTY_FILE
for each line in file1:
  if not line in file2:
    file2.append(line)

Ceci est potentiellement assez lent, surtout s’il est implémenté au niveau Bash. Mais si vos fichiers sont raisonnablement courts, cela fonctionnera probablement très bien et sera rapide à mettre en œuvre ( pas la ligne dans le fichier 2 est alors juste grep -v , etc.). ).

Sinon, vous pourriez bien sûr coder un programme dédié en utilisant une structure de données plus avancée en mémoire pour l'accélérer.

for line in $(sort file1 | uniq ); do
    grep -n -m1 line file >>out
done;

sort -n out

d'abord faire le tri,

pour chaque valeur unitaire grep pour la première correspondance (-m1)

et conservez les numéros de ligne

trie la sortie numériquement (-n) par numéro de ligne.

vous pouvez ensuite supprimer la ligne # avec Sed ou awk

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top