代码之家  ›  专栏  ›  技术社区  ›  Shawn Craver

如何将Perl的split命令与空白剪裁结合起来?

  •  4
  • Shawn Craver  · 技术社区  · 17 年前

    Repost from 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 回复  |  直到 17 年前
        1
  •  11
  •   Ether    17 年前

    您不必使用相同的函数一次性完成这两个操作。有时单独执行操作会更清楚。也就是说,先拆分,然后去掉每个元素的空白(然后对结果进行排序):

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

    编辑:同时剥离一个字符串的多个部分可能会导致陷阱,例如下面的Sinan关于在“Elizabeth”部分留下尾随空格的观点。我用这样一个假设来编码这段代码,即该名称不会有内部空白,这实际上是非常错误的,如果我有意识地注意到它,它会显得非常不正确。代码在下面得到了很大的改进(而且可读性更高):

    @email_list =
        sort(
            map {   
                    s/^\s+//;  # strip leading spaces
                    s/\s+$//;  # strip trailing spaces
                    $_         # return the modified string
                }
                split ';', $file_data
        );
    
        2
  •  11
  •   C. K. Young    17 年前

    如果您不需要修剪第一个和最后一个元素,这将实现以下技巧:

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

    如果您确实需要修剪第一个和最后一个元素,修剪 $file_data 首先,然后如上所述重复。:-p

        3
  •  2
  •   user80168    17 年前

    好吧,你可以按照克里斯的建议去做,但是它不处理$file_数据中的前导空格和尾随空格。

    您可以这样添加对这些的处理:

    $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";
    }
    
        4
  •  1
  •   ysth    17 年前
    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;
    
        5
  •  1
  •   Sinan Ünür    17 年前

    How do I strip blank space from the beginning/end of a string? 在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+$//;
    }
    

    也可以。

        6
  •  0
  •   Axeman maxelost    17 年前

    轮到我了:

    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];
    

    是最可靠的方法。

        7
  •  -1
  •   Kristoffon    17 年前

    除了一些小的sintax错误,这应该可以为您完成全部工作。哦,列表操作,你真漂亮!

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