Perl修剪标量或数组的空间

dal*_*sam 1 perl

这是一个非常基本的Perl问题,但我只是想确保实际的良好实践.

考虑我已经构建了一个函数来修剪字符串中的空格,我会将单个标量作为字符串或字符串数​​组传递给它,我有这个基本的工作示例:

sub trim_spaces {
    my (@out) = @_;
    for (@out) {
        s/\s+//g;
    }
    return (scalar @out >1)? @out : $out[0];
}
Run Code Online (Sandbox Code Playgroud)

这适用于以下调用:

trim_spaces("  These Spaces Are All Removed");
Run Code Online (Sandbox Code Playgroud)

@str = (" Str Number 1 ", " Str Number 2 ", " Str Number 3 ");
trim_spaces(@str);
Run Code Online (Sandbox Code Playgroud)

我想要做的和理解的是这个函数的最短版本,如下所示:

sub trim_spaces {
    s/\s+//g for (@_);
    return @_;
}
Run Code Online (Sandbox Code Playgroud)

这只有在我传递数组时才有效:

trim_spaces(@str);
Run Code Online (Sandbox Code Playgroud)

但是如果我传递一个标量字符串它不起作用:

trim_spaces("  These Spaces Are All Removed");
Run Code Online (Sandbox Code Playgroud)

我知道它应该从标量ref转换为数组,如何在短版本中完成.

试图了解Perl的最佳实践.

Sla*_*ade 5

对此的严格最佳实践答案是始终将内容解包@_为词法变量.Perl最佳实践提供以下(释义)参数:

  • 直接访问不是自我记录@_.$_[0],$_[1]等等,告诉你这些参数的用途.

  • 别名行为@_很容易被遗忘,并且可能成为程序中难以发现的错误的来源.尽可能避免远处的怪异动作.

  • 您可以在解压缩@_数组时验证每个参数.

一个论点不是来自PBP:

  • 看到my $self = shift;子程序的开头清楚地将其标记为OO方法而不是普通的子程序.

资料来源:Perl最佳实践(Conway 2005),Perl ::来自PBP的评论家的相关政策.


@_中的元素是原始值的别名,这意味着在子例程中修改它们也会将它们更改为外部值.您返回的数组将在示例中被忽略.

如果将字符串存储在变量中,这将起作用:

my $string = '  These Spaces Are Removed   ';
trim_spaces($string); # $string is now 'TheseSpacesAreRemoved'
Run Code Online (Sandbox Code Playgroud)

或者您可以使用非破坏性替换并分配由此创建的结果:

sub trim_spaces { return map { s/\s+//gr } @_ }
my @trimmed = trim_spaces('string one', ' string two');
my ($trimmed_scalar) = trim_spaces('string three');
Run Code Online (Sandbox Code Playgroud)

map将创建值列表[R通过与替代eturned /r标志.$ trimmed_scalar周围的parens是必要的; 请参阅最后一个不是版本的示例.

或者,您可以将子例程中的参数复制到词法变量中以避免在远处执行操作,这通常比直接修改@_的元素更好:

sub trim_spaces
{
    my @strings = @_;
    s/\s+//g for @strings;
    return @strings;
}
Run Code Online (Sandbox Code Playgroud)

就个人而言,当子程序返回没有副作用的值时,我发现它更好,并且该/r标志使我省去了为词法副本考虑更好名称的麻烦.我们可以使用wantarray它来调用上下文:

sub trim_spaces
{
    return if not defined wantarray;
    return map { s/\s+//gr } @_ if wantarray;
    return shift =~ s/\s+//gr;
}
Run Code Online (Sandbox Code Playgroud)

在旁注中,trim_spaces会更好地命名remove_whitespace或类似的东西.修剪通常意味着删除前导和尾随空格,除了空格外,\s字符类还匹配制表符,换行符,换页符和回车符.tr/ //dcr如果这是您想要的,请使用以删除空格.