Как я могу объединить команду разделения Perl с обрезкой пробелов? - PullRequest
4 голосов
/ 11 августа 2009

Репост от Perlmonks для сотрудника:

Я написал Perl-скрипт для разделения длинных списков писем, разделенных точкой с запятой. Что я хотел бы сделать с кодом, так это объединить разбиение с усечением пустого пространства, поэтому мне не нужны два массива. Есть ли урезать при загрузке первого массива. Вывод представляет собой отсортированный список имен. Спасибо.

#!/pw/prod/svr4/bin/perl
use warnings;
use strict;

my $file_data =
  'Builder, Bob  ;Stein, Franklin MSW; Boop, Elizabeth PHD   Cc: Bear,
+ Izzy';
my @email_list;

$file_data =~ s/CC:/;/ig;
$file_data =~ s/PHD//ig;
$file_data =~ s/MSW//ig;

my @tmp_data = split( /;/, $file_data );

foreach my $entry (@tmp_data) {
    $entry =~ s/^[ \t]+|[ \t]+$//g;
    push( @email_list, $entry );
}

foreach my $name ( sort(@email_list) ) {
    print "$name \n";
}

Ответы [ 7 ]

11 голосов
/ 11 августа 2009

Вам не нужно выполнять обе операции за один раз, используя одну и ту же функцию. Иногда выполнение действий по отдельности может быть более понятным. То есть сначала разделите, а затем удалите пробелы из каждого элемента (а затем отсортируйте результат):

@email_list =
    sort(
        map {
                s/\s*(\S+)\s*/\1/; $_
            }
            split ';', $file_data
    );

РЕДАКТИРОВАТЬ: удаление более одной части строки одновременно может привести к ошибкам, например, Ниже указывается Синан о том, как оставить пробелы в части "Элизабет". Я закодировал этот фрагмент с предположением, что у имени не будет внутреннего пробела, что на самом деле совершенно неверно и выглядело бы как неправильное, если бы я его сознательно заметил. Код значительно улучшен (и также более читабелен) ниже:

@email_list =
    sort(
        map {   
                s/^\s+//;  # strip leading spaces
                s/\s+$//;  # strip trailing spaces
                $_         # return the modified string
            }
            split ';', $file_data
    );
11 голосов
/ 11 августа 2009

Если вам не нужно обрезать первый и последний элемент, это поможет:

@email_list = split /\s*;\s*/, $file_data;

Если вам нужно обрезать первый и последний элемент, сначала обрежьте $file_data, затем повторите, как указано выше. : -Р

2 голосов
/ 11 августа 2009

Что ж, вы можете сделать то, что предложил Крис, но он не обрабатывает начальные и конечные пробелы в $ file_data.

Вы можете добавить обработку следующим образом:

$file_data =~ s/\A\s+|\s+\z//g;

Также обратите внимание, что использование второго массива не было необходимым. Проверьте это:

my $file_data = 'Builder, Bob  ;Stein, Franklin MSW; Boop, Elizabeth PHD   Cc: Bear, Izzy';
my @email_list;

$file_data =~ s/CC:/;/ig;
$file_data =~ s/PHD//ig;
$file_data =~ s/MSW//ig;

my @tmp_data = split( /;/, $file_data );

foreach my $entry (@tmp_data) {
    $entry =~ s/^[ \t]+|[ \t]+$//g;
}

foreach my $name ( sort(@tmp_data) ) {
    print "$name \n";
}
1 голос
/ 11 августа 2009

См. Как убрать пробел из начала / конца строки? в FAQ.

@email_list = sort map {
    s/^\s+//; s/\s+$//; $_
} split ';', $file_data;

Теперь обратите внимание также, что цикл for создает псевдонимы для каждого элемента массива, поэтому

@email_list = sort split ';', $file_data;

for (@email_list) {
    s/^\s+//;
    s/\s+$//;
}

также будет работать.

1 голос
/ 11 августа 2009
my @email_list = map { s/^[ \t]+|[ \t]+$//g; $_ } split /;/, $file_data;

или более элегантный:

use Algorithm::Loops "Filter";
my @email_list = Filter { s/^[ \t]+|[ \t]+$//g } split /;/, $file_data;
0 голосов
/ 11 августа 2009

Мой ход:

my @fields = grep { $_ } split m/\s*(?:;|^|$)\s*/, $record;

Также удаляет первый и последний элементы. Если grep лишнее для избавления от первого элемента:

my ( undef, @fields ) = split m/\s*(?:;|^|$)\s*/, $record;

работает, если знает , что есть пробел, но это маловероятно, поэтому

my @fields = split m/\s*(?:;|^|$)\s*/, $record;
shift @fields unless $fields[0];

- самый верный способ сделать это.

0 голосов
/ 11 августа 2009

За исключением незначительной ошибки синтаксиса, это должно сделать всю работу за вас. О, список операций, как ты прекрасна!

print join (" \n", sort { $a <=> $b } map { s/^[ \t]+|[ \t]+$//g } split (/;/, $file_data));
...