Suchen und löschen Sie nahezu doppelte Zeilen mit bestimmter Zeichensetzung

Suchen und löschen Sie nahezu doppelte Zeilen mit bestimmter Zeichensetzung

Ich habe eine Textdatei mit Millionen von Zeilen. Einige Zeilen enthalten dieselbe alphanumerische Sequenz, unterscheiden sich aber in Groß- und Kleinschreibung und Zeichensetzung. Ich betrachte diese Zeilen als Duplikate. Ich möchte alle doppelten Zeilen mit Punkten entfernen, aber die andere Zeile behalten (diese andere Zeile enthält normalerweise Zeichensetzung wie Unterstriche oder Bindestriche).

Eingang:

000
111
12_34
12.34
123-456-789
123.456.789
A.B.C
a_b_c
qwerty
qwertx
abcdefghijklm.nopqrstuvwxy.z
a-B-cdeFghiJklmNopqRStuvwxy__Z
22.2
33.3

Gewünschte Ausgabe:

000
111
12_34
123-456-789
a_b_c
qwerty
qwertx
a-B-cdeFghiJklmNopqRStuvwxy__Z
22.2
33.3

Antwort1

Vorausgesetzt, die doppelten Werte sind zusammenhängend!


Ein Perl-Skript, das diese Aufgabe erledigt.

Nicht an großen Dateien getestet!

#!/usr/bin/perl
use strict;
use warnings;

my $file = 'file1'; # path to input file
# read the input file in memory
open my $F, '<', $file or die "unable to open '$file': $!";
my @list = <$F>;chomp @list;
# delete all . - _ from each line and add this new string in the array for comparison
my @res = map {my $tmp=$_; tr/._-//d; [lc$_,$tmp] } @list;
# memoize the first values
my $prev_tst = $res[0][0];  # contains the string without punctuation
my $prev_orig = $res[0][1]; # contains original string
# loop on other values
for my $ind (1 .. @res-1) {
    my ($tst, $orig) = ($res[$ind][0], $res[$ind][1]);
    # te string without punctuation is the same as the previous
    if ($tst eq $prev_tst) {
        # if the previous original value contains dot
        if ($prev_orig =~  tr/.//) {
            # delete it
            undef $res[$ind-1];
        # if the current original value contains dot
        } elsif ($orig =~ tr/.//) {
            # delete it
            undef $res[$ind];
        }
    }
    # memorize value for next step
    $prev_tst = $tst;
    $prev_orig = $orig;
}
# write result to result file
my $result = 'result_file'; # path to result file
open my $R, '>', $result or die "unable to open '$result': $!";

for (@res) {
    next unless defined $_; # skip undifned values
    print $R $_->[1],"\n";
}


Antwort2

Etwas in der Art von

sed 's/\./-/g; s/__*/-/g' /path/to/infile | sort -u > /path/to/outfile

sollte funktionieren

verwandte Informationen