Попытка извлечь уникальные строки из текстового файла в Perl - PullRequest
0 голосов
/ 12 октября 2018

Я 5 дней изучаю Perl, и у меня возникла эта проблема.Попытка извлечь определенную строку из файла с помощью регулярного выражения и поместить эти строки в резкое и вывести только OUT только уникальные значения, например, текстовый файл содержит строки типа:

             "placement Z  F97342" 
             "placement Z  F97342"
             "placement d  F97342"
             "placement g  F97342" 
             "placement Z  F97342" 

Ожидаемый результат:

            "placement Z  F97342"
            "placement d  F97342"
            "placement g  F97342"

Ниже приведен мой код, но он дает мне повторяющиеся строки с "расположением Z"

             open(FHR, "<test.txt") or die "Cannot open file $!";

            while (<FHR>){

            chomp($_);
            $_ =~/placement/g;

            print "$_\n";

            }

Любая помощь?

Ответы [ 3 ]

0 голосов
/ 12 октября 2018

В таких случаях действительно нет необходимости явно открывать файловые дескрипторы.Perl автоматически откроет все файлы, имена которых указаны в командной строке, и вы можете прочитать их данные, используя пустой оператор ввода файлов (<>).

Таким образом, ваш код может быть простым, как этот:

#!/usr/bin/perl

use strict;
use warnings;

my %seen;

while (<>) {
  print unless $seen{$_}++;
}

И если этот код находится в файле с именем filter, вы можете назвать его так:

$ filter test.txt
0 голосов
/ 12 октября 2018

с использованием Perl-однострочника

> cat file.txt
             "placement Z  F97342"
             "placement Z  F97342"
             "placement d  F97342"
             "placement g  F97342"
             "placement Z  F97342"
> perl -ne  '{ print "$_" unless $data{$_}++; } ' file.txt
             "placement Z  F97342"
             "placement d  F97342"
             "placement g  F97342"
>
0 голосов
/ 12 октября 2018

Вы неправильно поняли кучу вещей, я думаю.Вы делаете совпадение с регулярным выражением, но потом ничего не делаете с результатом.

Как вы думаете:

        $_ =~/placement/g;

делает?(Потому что ответ «ничего» прямо сейчас).

И точно так же - вы просто печатаете $_ на ходу, то есть буквально просто печатаете каждую строку в файле.

На каком уровне вам нужно тестировать дубликаты?Это «полная строка» или просто «место размещения» или «число» после него?

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

Что-то вроде этого поможет:

#!/usr/bin/env perl

use strict;
use warnings;

open( my $input, '<', "test.txt" ) or die "Cannot open file $!";

my %seen; 

while (my $line = <$input>) {
   print $line unless $seen{$line}++;
}

Также:

  • Хорошо использовать лексические файловые дескрипторы с открытым 3 аргументом.Мой пример отражает это.
  • получите perltidy и используйте его.perltidy -pbp сделает отступ и отформатирует ваш код в соответствии с общепринятым стандартом.(Вы можете настроить его так, как вам нравится - форматирование / отступ могут быть любыми, если они согласуются ).
  • Вам не нужно chomp, если все, что вы делаете, это заново вводите перевод строки вручную.
  • Вы должны ВСЕГДА use strict; и use warnings;.

Если вы хотите быть более избирательными в отношении того, какой бит строки проверять на дубликаты, вы можете захватывать подэлементы с помощью регулярных выражений.Скажем, к примеру - имеет значение только «буква размещения»:

#!/usr/bin/env perl

use strict;
use warnings;

open( my $input, '<', "test.txt" ) or die "Cannot open file $!";

my %seen; 

while ( <$input>) {
   my ( $placement_id ) = m/placement (\d+)/;
   print unless $seen{$placement_id}++;
}

Обратите внимание, здесь - я не назначаю содержание <$input> - оно установлено на $_, но я чувствую себя как точка стилявам следует избегать использования $_ в вашем коде - назовите его, если вы собираетесь его использовать.

Это работает, потому что оба m// соответствия регулярного выражения и print оба по умолчанию работают на $_, который является "текущей строкой".Скобки в регулярном выражении с правой стороны используются для заполнения $placement_id - но учтите, что нужно скобок с левой стороны, потому что в противном случае $placement_id_ будет только 'true / false'результат соответствия шаблона.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...