【问题标题】:Perl regex wrongfully evaluating expressionsPerl 正则表达式错误地评估表达式
【发布时间】:2018-04-22 19:20:44
【问题描述】:

我有以下带有字符串的 perl 代码,我需要检查几个案例以确定如何处理它。它们都不起作用。代码如下所示:

my $param = "02 1999";
my @months = qw(january february march april may june july august september october november december);

my $white = /^\s*$/; #check if all whitespace
my $singleyear = /^\d{2,4}$/; #check if 2-4 digits
my $nummonth = /^\d{1,2}\s\d{1,4}$/; #check if 1-2 digits then 1-4

if ($param =~ $white) {
    my($day, $month, $year)=(localtime)[3,4,5];
    my $monthname = $months[$month]; 
    print "$monthname $year\n";
}
if ($param =~ $singleyear) {
    print "$param\n";
}
if ($param =~ $nummonth) {
    my $monthnumber = $param =~ /^\d{1,2}/; #grabs the number at the front of the string
    my $monthstring = $months[$monthnumber]; 
    my $yearnumber = $param =~ /(\d{1,4})$/; #grab second number, it does this wrong
    print "$monthstring $yearnumber\n";
}

鉴于上述情况,输出应该是:

february 1999

相反,输出是:

3 118
02 1999
february 1 #this only grabbed the first digit for some reason.

因此,出于某种原因,所有案例都被评估为真实,而当年的捕获甚至都没有奏效。我究竟做错了什么?在 regex101 测试我所有的正则表达式都很好,但不是在脚本中。

【问题讨论】:

  • 您的代码包含多个语法错误。先修复这些问题,然后启用use strict; use warnings; 并重试。
  • my $yearnumber = $param =~ /(\d{1,4})$/; 并没有按照你的想法去做。
  • my $white = /^\s*$/; 也没有,但我发现很难用甚至不解析的代码来正确解释事情,更不用说传递 strictwarnings
  • @melpomene 出于格式原因,我主要从我的代码转录到这篇文章,对于任何拼写错误,我深表歉意。它在我执行它的地方运行没有错误,讽刺的是strictwarnings。我修复了帖子中缺少的几个分号。
  • 您的代码没有通过strict(未声明的变量,缺少$)。一旦你解决了这个问题,你会看到一个(希望是)有用的警告。

标签: regex perl


【解决方案1】:

我发现两个问题对您的问题很重要。

首先,您显然希望将预编译的正则表达式保存在变量 $white$singleyear$nummonth 中,但您没有使用正确的运算符 - 您应该使用 qr// 编译并保存正则表达式。像my $white = /^\s*$/; 这样的代码将运行针对$_ 的正则表达式并将结果存储在$white

其次,my $monthnumber = $param =~ /^\d{1,2}/; 有两个问题:在标量上下文中与m// 一起使用的=~ operator 只会返回一个真/假值(即您在输出february 1 中看到的1),但是如果您想从正则表达式中获取捕获组,您需要在列表上下文中使用它,在这种情况下通过说my ($monthnumber) = ...(同样的问题适用于$yearnumber)。其次,该正则表达式不包含任何捕获组!

我没有得到您声称的确切输出(尽管它很接近) - 请查看Minimal, Complete, and Verifiable example,尤其是因为您的帖子最初包含很多语法错误。如果我应用上面描述的修复程序,我会得到输出

march 1999

这正是我所期望的——我希望你能弄清楚如何解决这个错误。

更新:我应该补充一点,您也不需要自己尝试解析日期/时间。我最喜欢的日期/时间处理模块是DateTime(连同DateTime::Format::Strptime),但在这种情况下,核心Time::Piece就足够了:

use Time::Piece;
my $param = "02 1999";
my $dt = Time::Piece->strptime($param, "%m %Y");
print $dt->fullmonth, " ", $dt->year, "\n";       # prints "February 1999"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多