Perl 从标量或数组修剪空间

标签 perl

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

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

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

这适用于以下调用:

trim_spaces("  These Spaces Are All Removed");

@str = (" Str Number 1 ", " Str Number 2 ", " Str Number 3 ");
trim_spaces(@str);

我想做的和理解的是这个函数的最短版本:

sub trim_spaces {
    s/\s+//g for (@_);
    return @_;
}

这仅在我传递一个数组时有效:

trim_spaces(@str);

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

trim_spaces("  These Spaces Are All Removed");

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

尝试了解 Perl 的最佳实践。

最佳答案

对此的严格最佳实践答案是总是首先将 @_ 的内容解压到词法变量中。 Perl Best Practices 提供了以下(转述的)论点:

  • 直接访问@_ 不是自文档。 $_[0]$_[1] 等没有告诉您这些参数的用途。

  • @_ 的别名行为很容易被遗忘,并且可能成为程序中难以发现的错误的来源。尽可能避免远距离的诡异 Action 。

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

还有一个论点不是来自 PBP:

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

来源:Perl 最佳实践(Conway 2005),Perl::Critic来自 PBP 的相关政策。


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

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

my $string = '  These Spaces Are Removed   ';
trim_spaces($string); # $string is now 'TheseSpacesAreRemoved'

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

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

map 将创建一个值列表,其中包含 r 通过使用 /r 标志进行替换而返回的值。 $trimmed_scalar 周围的括号是必要的;请参阅最后一个示例,了解它不是的版本。

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

sub trim_spaces
{
    my @strings = @_;
    s/\s+//g for @strings;
    return @strings;
}

就我个人而言,我发现子例程返回一个没有副作用的值会更好,而且 /r 标志让我省去了为词法副本考虑更好名称的麻烦。我们可以使用 wantarray 使其在调用上下文方面更加智能:

sub trim_spaces
{
    return if not defined wantarray;
    return map { s/\s+//gr } @_ if wantarray;
    return shift =~ s/\s+//gr;
}

旁注,trim_spaces 最好命名为 remove_whitespace 或类似名称。修剪通常意味着去除前导和尾随空格,\s 字符类除了空格之外还匹配制表符、换行符、换页符和回车符。如果您需要,请使用 tr///dcr 只删除空格。

关于Perl 从标量或数组修剪空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25323679/

相关文章:

perl - Perl 中的校验和

perl - 应该使用CGI.pm的header方法来输出Content-Type header吗?

perl - 通过 $_ 打开命令行上提供的文件名是否存在问题?

r - 加载 gdata 包时如何修复 Perl 警告消息?

regex - perl regexp 与 sas - 精确匹配其中之一

perl - 如何在 Perl 中将 "image"标签添加到 mp3 文件

linux - asmcmd 返回错误 "Can' t 在 @INC 中找到模块 DBI 的可加载对象”

mysql - 为什么这个 MySQL 语句不起作用?

perl - 使用系统时向家长传播信号

regex - Perl 正则表达式从哈希替代