Удалить дубликаты из списка файлов в Perl - PullRequest
0 голосов
/ 25 декабря 2010

Я знаю, что это должно быть довольно просто, и версия оболочки выглядит примерно так:

$ sort example.txt | uniq -u

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

Ответы [ 4 ]

1 голос
/ 25 декабря 2010

Интересным спином в этом вопросе является uniq -u!Я не думаю, что другие ответы, которые я видел, касаются этого;они имеют дело с sort -u example.txt или (несколько расточительно) sort example.txt | uniq.

Разница в том, что опция -u устраняет все вхождения дублированных строк, поэтому на выходе выводятся строки, которые появляются только один раз.

Чтобы решить эту проблему, вам нужно знать, сколько раз каждое имя появляется, а затем вам нужно напечатать имена, которые появляются только один раз.Предполагая, что список должен быть прочитан из стандартного ввода, тогда этот код делает трюк:

my %counts;
while (<>)
{
    chomp;
    $counts{$_}++;
}

foreach my $name (sort keys %counts)
{
    print "$name\n" if $counts{$name} == 1;
}

Или, используя grep:

my %counts;
while (<>)
{
    chomp;
    $counts{$_}++;
}

{
local $, = "\n";
print grep { $counts{$_} == 1 } sort keys %counts;
}

Или, если вы ненеобходимо удалить символы новой строки (потому что вы собираетесь печатать только имена):

my %counts;
$counts{$_}++ for (<>);
print grep { $counts{$_} == 1 } sort keys %counts;

Если вы действительно хотите, чтобы каждое имя, которое появляется на входе, появлялось на выходе (но только один раз)), тогда любое из других решений сделает свое дело (или, с минимальной адаптацией, сделает свое дело).Фактически, поскольку строки ввода заканчиваются символом новой строки, вы можете сгенерировать ответ всего в двух строках:

my %counts = map { $_, 1 } <>;
print sort keys %counts;

Нет, вы не можете сделать это в одной, просто заменив %counts вprint строка с map в первой строке:

print sort keys map { $_, 1 } <>;

Вы получаете ошибку:

Type of arg 1 to keys must be hash or array (not map iterator) at ...
0 голосов
/ 25 декабря 2010

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

Предполагая последнее:

my %seen;
@filenames = grep !$seen{$_}++, @filenames;

или другие решения из perldoc -q duplicate

0 голосов
/ 25 декабря 2010

Прежде всего, sort -u xxx.txt был бы умнее, чем sort | uniq -u.

Во-вторых, perl -ne 'print unless $seen{$_}++' склонен к целочисленному переполнению, поэтому более сложный способ perl -ne 'if(!$seen{$_}){print;$seen{$_}=1}' кажется предпочтительным.

0 голосов
/ 25 декабря 2010

или используйте подпрограмму 'uniq' из модуля List :: MoreUtils после чтения всего файла в список (хотя это не очень хорошее решение)

...