2012-11-22 84 views
1

在一个Perl/Tk的代码,我发现了一个条件语句如下在Perl中,if(s/^ + //)的含义是什么?

if (s/^\+//) 
{ 
    #do something 
} 
elsif (/^-/) 
{ 
    #do another thing 
} 

好像一些模式匹配已经完成。但我无法理解它。任何人都可以帮我理解这种模式匹配吗?

+2

@Oded,该链接ISN这是我见过的最糟糕的Perl教程,但它比较老,使用一些过时的做法('-w' vs'warnings',prototypes)。我可能会推荐['perldoc perlretut'](http://p3rl.org/retut)。 –

+0

@JoelBerger - 够公平的。这是谷歌第一次点击。 – Oded

+3

@Oded,NP。 Perl教程的长久性是社区通过制作/突出更新的更好的教程来努力争取的,并且警告关于老教师/坏教师的问题http://perl-tutorial.org/。在互联网泡沫带来很多糟糕的代码之后,Perl得到了一个不好的名字,我们试图一次性改进一个教程。 –

回答

11

它们都是正则表达式。您可以在perlreperlretut上阅读。你可以在http://www.rubular.com上与他们玩。

它们都隐含地做了$_。你的代码行可能有一个whileforeach而没有循环变量。在那种情况下,$_成为该循环变量。它可能包含正在读取的文件的当前行。

  1. 如果$_当前值包含+(加号)作为字符串,#do somehting开始的第一个字符。
  2. 否则,如果它包含-(负号),#do another thing

在案例1中,它也将该符号替换为+(即删除它)。但它不会删除2中的-


让我们看看YAPE::Regex::Explain的解释。

use YAPE::Regex::Explain; 
print YAPE::Regex::Explain->new(qr/^\+/)->explain(); 

这是它。在我们的案例中不是很有帮助,但是却是一个不错的工具。请注意,(?-imsx)部分是Perl暗示的默认东西。除非你改变它们,它们总是在那里。

The regular expression: 

(?-imsx:^\+) 

matches as follows: 

NODE      EXPLANATION 
---------------------------------------------------------------------- 
(?-imsx:     group, but do not capture (case-sensitive) 
         (with^and $ matching normally) (with . not 
         matching \n) (matching whitespace and # 
         normally): 
---------------------------------------------------------------------- 
^      the beginning of the string 
---------------------------------------------------------------------- 
    \+      '+' 
---------------------------------------------------------------------- 
)      end of grouping 
---------------------------------------------------------------------- 

更新:作为米科L的评论中指出,应重构也许/更改这段代码。虽然它可能做到了它应有的目标,但我相信这会让它更具可读性。谁写的显然不关心你作为后来的维护者。我建议你这样做。您可以将其更改为:

# look at the content of $_ (current line?) 
if (s/^\+//) 
{ 
    # the line starts with a + sign, 
    # which we remove! 

    #do something 
} 
elsif (m/^-/) 
{ 
    # the line starts witha - sign 
    # we do NOT remove the - sign! 

    #do another thing 
} 
+1

您的分析是点亮的。我会补充说OP应该考虑重构这段代码,以便替换更明显。以现在写的方式错过它很容易。甚至简单地去'if(/^\ + /){$ _ =〜s/^ \ + //; #做点什么}'会有相当大的帮助。 –

+0

@MikkoL我同意并添加了这些建议。我不同意明确使用'$ _',但这是我个人的偏好。谢谢。 – simbabque

+1

Downvoter,你是否喜欢评论我如何改进我的帖子? – simbabque

5

这些是正则表达式,用于模式匹配和替换。

你应该在概念读了,但你的问题:

s/^\+// 

如果字符串开始有加,除去加(以下简称“s”表示“替代”),并返回true 。

/^-/ 

如果字符串以负号开头,则为true。

3

该代码相当于

if ($_ =~ s/^\+//) { # s/// modifies $_ by default 
    #do something 
} 
elsif ($_ =~ m/^-/) { # m// searches $_ by default 
    #do another thing 
} 

s///m//是正则表达式报价状运算符。你可以在perlop阅读。

+2

这是一个非常好的(尽管很短)的答案。我不明白为什么它是downvoted。 – simbabque

+1

我没有downvote,但我确定它是因为,隐式变量在这里没有问题,而是替代模式本身。 –

2

其他答案给出了代码如何工作的总结,但没有太多的原因。以下是为什么可以使用这种逻辑的一个简单例子。

#!/usr/bin/env perl 

use strict; 
use warnings; 

my $args = {}; 

for (@ARGV) { 
    if (s/^no//) { 
    $args->{$_} = 0; 
    } else { 
    $args->{$_} = 1; 
    } 
} 

use Data::Dumper; 
print Dumper $args; 

当你调用像

./test.pl hi nobye 

脚本你

$VAR1 = { 
      'hi' => 1, 
      'bye' => 0 
     }; 

的关键是字符串,但是如果它是由no前面,然后将其删除(拿到钥匙有问题),而是将值设置为0

OP的例子有一点涉及,但遵循相同的逻辑。

  • 如果有+钥匙启动,删除它,然后做一些
  • 如果有-钥匙启动,请不要删除它,做别的事情
+0

@downvoter,关心评论? –

相关问题