2010-07-02 41 views
4

如何使用带分割功能的地图来修剪组成部分:$ a,$ b,$ c和$ d; $行?在Perl中使用拆分和修剪的地图

my ($a, $b, $c, $d, $e) = split(/\t/, $line); 

# Perl trim function to remove whitespace from the start and end of the string 
sub trim($) 
{ 
    my $string = shift; 
    $string =~ s/^\s+//; 
    $string =~ s/\s+$//; 
    return $string; 
} 

回答

2

这应该工作:

my ($a, $b, $c, $d, $e) = map {trim ($_)} (split(/\t/, $line)); 

顺便说一句,这是一个小点,但你不应该使用$ a和$ b作为变量名。

3

map有两个输入端:

  • 一个表达式或块:这将是trim表达式(你没有写自己的 - 这是对CPAN)
  • ,操作列表于:这应该是split的输出:
use String::Util 'trim'; 
my @values = map { trim($_) } split /\t/, $line; 
+1

我担心引入模块上的依赖它说“最终版本,该版本字符串::的Util不再是正在开发或支撑。 “。 – 2010-07-02 03:05:49

+0

如果我们要安装一个CPAN模块,我们不妨使用最好的工作:['String :: Strip'](http://p3rl.org/String:Strip)。见http://www.illusori.co.uk/perl/2010/03/05/advanced_benchmark_analysis_1.html – daxim 2010-07-02 09:23:05

+0

我还没有尝试过,但对于这些模块的酸性测试是否它们去掉了Unicode 0x3000来自字符串。如果不是,那么它可能不是一个好的替代品。纵观源代码,String :: Strip使用C函数'isspace'去掉空格,并且不知道unicode,所以它的行为与上述不同。 – 2010-07-02 09:58:35

4

不要使用原型你的功能上的($)除非你需要他们。

my ($a, $b, $c, $d, $e) = 
    map {s/^\s+|\s+$//g; $_} ## Notice the `, $_` this is common 
    , split(/\t/, $line, 5) 
; 

在上面不要忘记s///返回更换计数 - 不$_。所以,我们明确地这样做。

或者更简单地说:

my @values = map {s/^\s+|\s+$//g; $_}, split(/\t/, $line, 5), $line 
+0

为什么要投票? – 2010-07-02 03:33:21

+0

我不知道为什么downvote,但你已经忘了最后一行中的g。 – 2010-07-02 03:44:05

+0

为什么你建议不要原型? – mleykamp 2010-07-02 16:07:43

0

只是为了多种:

my @trimmed = grep { s/^\s*|\s*$//g } split /\t/, $line; 

grep作为上列出的过滤器。这就是为什么需要在正则表达式中将\s+更改为\s*的原因。强制匹配0或更多空格可防止grep过滤掉列表中没有前导或尾随空格的项目。

+0

但它不包含被标签包围且没有空格的段。 '“\ tspoon \ t”'会被省略。 – Axeman 2010-07-02 13:01:45

+0

@Axeman:从['perlretut'](http://perldoc.perl.org/perlretut.html):''\ s'匹配一个空白字符,集合'[\ \ t \ r \ n \ f] '和其他人。“另外,我们不是在这里分开'\ t';)? – Zaid 2010-07-02 13:24:24

+0

是的 - 但没关系,我的眼睛用我平常的'\ s +'取代了'\ s *'。所以总是匹配,我不知道我在说什么。 :D – Axeman 2010-07-02 16:16:53

1

你也可以在这里使用“foreach”。

foreach my $i ($a, $b, $c, $d, $e) { 
    $i=trim($i); 
} 
0

当我修剪一个字符串时,我经常不想保留原文。有一个sub的抽象,但也不必大惊小怪临时值。

事实证明,我们所能做的只是这一点,因为perlsub解释说:

中显示出来的阵列@_传入任何参数。因此,如果您使用两个参数调用函数,那么这些函数将存储在$_[0]$_[1]中。数组@_是一个本地数组,但其元素是实际标量参数的别名。特别是,如果更新了元素$_[0],则会更新相应的参数(或者如果它不可更新,则会发生错误)。

在你的情况,trim成为

sub trim { 
    for (@_) { 
    s/^ \s+ //x; 
    s/ \s+ $//x; 
    } 
    wantarray ? @_ : $_[0]; 
} 

记住mapfor是堂兄弟,所以在trim循环,你不再需要map。例如

my $line = "1\t 2\t3 \t 4 \t 5 \n";  
my ($a, $b, $c, $d, $e) = split(/\t/, $line);  

print "BEFORE: [", join("] [" => $a, $b, $c, $d), "]\n"; 
trim $a, $b, $c, $d; 
print "AFTER: [", join("] [" => $a, $b, $c, $d), "]\n"; 

输出:

BEFORE: [1] [ 2] [3 ] [ 4 ] 
AFTER: [1] [2] [3] [4]
+0

你能解释'=>'连接的用法吗?我从来没有见过? – mleykamp 2010-07-02 16:12:01

+1

@ 10rd_n3r0,我会试穿一下,join中的第一个参数是一个特殊的参数,其他的都是一样的,“胖逗号”('=>')只是比' '。出于这个原因我自己使用它。比如在这种情况下,'keyword => qw words>'没有任何东西可以区分它们在创建的列表中,但是我正在展示我对它们的思考方式。如果在那些我希望用视觉分离来描述语义的时候,我会使用它。 – Axeman 2010-07-02 16:20:57

+0

@ 10rd我把它用于@Axeman所描述的视觉分离。正如我写的那样,我最初有'join(“,”=> ...)',并且每当分隔符包含一个逗号时,我喜欢用逗号来表示可读性。 – 2010-07-02 17:40:34