Как удалить повторяющиеся строки при игнорировании отдельных символов?

Мне нужно удалить все повторяющиеся строки из файла, но игнорируя все проявления этих символов:

(),、""。!?#

В качестве примера эти две строки будут считаться дублирующими, поэтому один из них будет удален:

"This is a line。"
This is a line

Точно так же эти три строки будут считаться дублирующими, и останется только один:

This is another line、 with more words。
"This is another line with more words。"
This is another line! with more words!
  • Не имеет значения, какая из повторяющихся строк остается в документе.
  • После удаления дубликатов порядок строк не должен изменяться.
  • Почти все строки имеют важную пунктуацию, но пунктуация может несколько отличаться. Какая бы ни была строка, все равно может быть пунктуация, поэтому пунктуация не должна быть удалена в конечном выходе.

Как я могу удалить все повторяющиеся строки в файле, игнорируя некоторые символы?

2 ответа

В вашем примере вы можете просто удалить свои символы, а затем удалить дубликаты.

Например:

$ cat foo
«This is a line¡»
This is another line! with more words¡

Similarly, these three lines would be considered duplicates, and only one would remain:
This is a line

This is another line, with more words!
This is another line with more words

$ tr --delete '¡!«»,' < foo | awk '!a[$0]++'
This is a line
This is another line with more words

Similarly these three lines would be considered duplicates and only one would remain:

$

Кажется, чтобы выполнить эту работу.

Редактировать:

Из вашего вопроса, похоже, эти символы/знаки препинания не имеют значения. Вы должны это точно уточнить.

У меня нет времени писать это, но я думаю, что простой способ должен состоять в том, чтобы проанализировать ваш файл и сохранить массив уже напечатанной строки:

for each line:
 cleanedLine = stripFromSymbol(line)
 if cleanedLine not in AlreadyPrinted:
 AlreadyPrinted.push(cleanedLine)
 print line


Это подход. Вы собираете их в массивы, набитые по нормализованной версии. Нормализованный здесь означает удаление всех символов, которые вам не нужны, и сквош-пространства тоже. Затем он выбирает самую короткую версию для печати/сохранения. Эвристика, которую нужно сохранить, на самом деле не была определена так, чтобы по вкусу. Кодекс немного точен для производства, поэтому вы можете использовать его для ясности.

use utf8;
use strictures;
use open qw/ :std :utf8 /;

my %tree;
while (my $original = <data>) {
 chomp $original;
 ( my $normalized = $original ) =~ tr/ (),、""。!?#/ /sd;
 push @{$tree{$normalized}}, $original;
 #print "O:",$original, $/; 
 #print "N:",$normalized, $/; 
}

@{$_} = sort { length $a <=> length $b } @{$_} for values %tree;

print $_->[0], $/ for values %tree;

__DATA__
"This is a line。"
This is a line
This is a line
This is another line、 with more words。
This is another line with more words
This is another line! with more words!
</data>

Yields-

This is another line with more words
This is a line

licensed under cc by-sa 3.0 with attribution.