如何对这个替换的Perl子程序进行高尔夫?

时间:2010-02-15 16:27:39

标签: perl

我在Perl中有以下子程序用“abc”替换字符串中的“xyz”:

sub mySubst {
    my ($str) = @_;
    $str =~ s|abc|xyz|ig;
    return $str;    
}

它有效,但对于Perl来说似乎过于冗长。我怎样才能收紧它?

9 个答案:

答案 0 :(得分:8)

你所拥有的一切都很好。

  • 使用列表赋值从@_变量中拉出参数,制作副本。列表分配是一种很好的方法(基本上是标准方式。)使用shift也可以,但更改@_(可能或可能不是您想要的。)There's a discussion on PerlMonks about shift vs @_您可能感兴趣的。
  • 您在搜索和替换时使用命名变量。在这种情况下,我更喜欢命名变量,因为处理Perl的魔术变量需要注意。
  • 自动处理$ _是可能的,但是没有$ _自动填充使得更难以正确。您需要执行local $_ = shift;local ($_) = @_;这不会增加太多。)
  • 当人们使用明确的return时,我喜欢它。这是一个温暖的模糊。
  • K& R Brackets。好。 :)
  • 没有原型。很好。 :)

一起去吧。我认为你走在正确的轨道上。

答案 1 :(得分:6)

如果您正在寻找高尔夫,并且生产代码。

use strict;   ## Not really required ;)
use warnings; ## Not really required ;)
sub f{local$_=pop,s/foo/bar/ig;$_}
print f 'foobarbaz';

答案 2 :(得分:3)

你可以写:

sub mySubst { (map { s|abc|xyz|ig; $_ } "$_[0]" )[0] }

但除非这是混淆的练习,否则我会说你有你的东西。请记住,您不是在为计算机编写程序。

答案 3 :(得分:3)

这就是我如何更惯用地渲染该子程序:

sub mySubst {
    (my $str = shift) =~ s|abc|xyz|ig;
    return $str;
}

答案 4 :(得分:1)

我认为太冗长听起来像没有足够的混淆我不同意。至于收紧它我建议采取以下措施:

sub replaceBeginningWithEnd {
    my $text = shift;
    return if not defined($text);
    $text =~ s/abc/xyz/ig;
    return $text;    
}
  • 让名字更具可读性
  • 使用惯例(即/ /反对|)
  • 参数检查

答案 5 :(得分:1)

没有人为此提供Perl成语。这通过修改副本来复制原始代码的行为:

  (my $new_str = $old_str) =~ s/abc/xyz/ig;

如果我不得不把它放到一个子程序中,我认为这对于这么简单的操作来说有点傻,我猜那会是:

 sub foo { (my $s = $_[0]) =~ s/abc/xyz/ig; $s }

但是,如果我这样做傻事,我就不会为它做一个命名的子程序。我做了一个子程序来为我制作子程序,所以我不需要为每种可能的替换方法都有一个新的命名子:

 sub make_sub {
      my( $regex, $replacement ) = @_;

      # season to taste with error checking
      sub {
          (my $s = $_[0]) =~ s/$regex/$replacement/ig; $s
          };
      }

 my $replacer = make_sub( qr/abc/, 'xyz' );

 my $new = $replacer->( $string );

答案 6 :(得分:0)

什么是子?就像这样做

$str =~ s|abc|xyz|ig;

答案 7 :(得分:0)

您可以省略return关键字:

sub mySubst {
    my ($str) = @_;
    $str =~ s|abc|xyz|ig;
    $str;    
}

也可以使用默认变量($_):

sub mySubst {
    local $_ = shift;  # or my starting from Perl 5.10
    s|abc|xyz|ig;
    $_;    
}

答案 8 :(得分:0)

为避免更改原件,您可以写

sub mySubst { map { (my $s=$_) =~ s|abc|xyz|ig; $s } @_ }

sub mySubst { my @a = @_; map { s|abc|xyz|ig; $_ } @a }

或借用Sinan的答案,除了明确丢弃临时数组:

sub mySubst { map { s|abc|xyz|ig; $_ } my(undef) = @_ }

但语法仍然有点吵。因为它使用map,所以请务必在列表上下文中调用它:

my($result) = mySubst $str;  # NOT my $one = mySubst $str;

如果您希望主要使用单个参数调用mySubst但想要处理一个或多个参数的情况,那么您可以编写

sub mySubst {
  s|abc|xyz|ig for my @a = @_;
  wantarray ? @a : $a[0];
}

但是这又开始了口吃。


如果您想更新参数本身,请使用perlsub中记录的Perl潜艇的别名语义:

  

数组@_是一个本地数组,但其元素是实际标量参数的别名。特别是,如果更新元素$_[0],则更新相应的参数(如果不可更新,则会发生错误)。

所以你可以写

sub mySubst { $_[0] =~ s|abc|xyz|ig }

甚至

sub mySubst { map { s|abc|xyz|ig; $_ } @_ }

使用示例:

$str = "fooabcbar";
mySubst $str;
print $str, "\n";

输出:

fooxyzbar