我正在编写一个程序,它有点模仿UNIX中的最后一个命令,我试图在我的解决方案中使用反向引用。我的程序完全按照它应该做的但我得到运行时错误/警告。我的问题是为什么会出现此错误/警告,我该如何解决这样的问题?
如果您需要我可以提供的更多信息。
程序执行
./last dodoherty
输出
Here is a listing of the logins for dodoherty:
1. dodohert pts/1 pc-618-012.omhq. Wed Feb 8 09:19 still logged in
2. dodohert pts/6 ip98-168-203-118 Tue Feb 7 19:19 - 20:50 (01:31)
3. dodohert pts/3 137.48.207.178 Tue Feb 7 14:00 - 15:06 (01:05)
4. dodohert pts/1 137.48.219.250 Tue Feb 7 12:32 - 12:36 (00:04)
5. dodohert pts/21 137.48.207.237 Tue Feb 7 12:07 - 12:23 (00:16)
6. dodohert pts/11 ip98-168-203-118 Mon Feb 6 20:50 - 23:29 (02:39)
7. dodohert pts/9 ip98-168-203-118 Mon Feb 6 20:31 - 22:57 (02:26)
8. dodohert pts/5 pc-618-012.omhq. Fri Feb 3 10:24 - 10:30 (00:05)
Use of uninitialized value $1 in addition (+) at ./odoherty_last.pl line 43.
Use of uninitialized value $2 in addition (+) at ./odoherty_last.pl line 44.
Here is a summary of the time spent on the system for dodoherty:
dodoherty
8
8:6
代码(错误来自的代码段,也是唯一一次使用$ 1和$ 2.)
foreach my $line2 (@user)
{
$line2 =~ /\S*\((\d{2,2})\:(\d{2,2})\)\s*/;
$hours = $hours + $1;
$mins = $mins + $2;
if( $mins >= 60 )
{
$hours = $hours + 1;
$mins = $mins - 60;
}
}
答案 0 :(得分:10)
我认为问题可能出在以下几行。
1. dodohert pts/1 pc-618-012.omhq. Wed Feb 8 09:19 still logged in
那是因为没有任何东西与模式相匹配所以$ 1和$ 2是未定义的。
答案 1 :(得分:4)
正如其他答案中所述,您的正则表达式不匹配,因此$1
和$2
未定义。在使用这些变量之前,必须始终检查以确保相应的正则表达式匹配。
下面我用一些正确的perl代码升级了你的脚本。在这种情况下,+=
和%=
是方便的运营商。您可以在perlop
你的正则表达式使用\S*
和\s*
,这两个都是完全没必要的,因为你的正则表达式没有锚定到其他任何东西。换句话说,\S*foo\s*
将匹配包含foo
的任何字符串,因为它可以匹配foo
周围的空字符串。另外,{2,2}
表示“匹配至少2次,最多2次”,实际上与{2}
“匹配2次”相同。
你会看到我改变了你的数学,那是因为它假定$mins
永远不会高于120.我认为从技术上讲,这是一个安全的假设,但是如下所示,它可以处理所有分钟值并成功将其转换为几小时。
以下脚本用于演示。如果您删除DATA
并离开<>
,则可以按原样使用此脚本:
last user | perl script.pl
<强>代码:强>
use strict;
use warnings;
use v5.10; # required for say()
my ($hours, $mins);
while (<DATA>) { # replace with while (<>) for live usage
if (/\((\d{2})\:(\d{2})\)/) {
$hours += $1;
$mins += $2;
if( $mins >= 60 ) {
$hours += int ($mins / 60); # take integer part of division
$mins %= 60; # remove excess minutes
}
}
}
say "Hours: $hours";
say "Mins : $mins";
__DATA__
1. dodohert pts/1 pc-618-012.omhq. Wed Feb 8 09:19 still logged in
2. dodohert pts/6 ip98-168-203-118 Tue Feb 7 19:19 - 20:50 (01:31)
3. dodohert pts/3 137.48.207.178 Tue Feb 7 14:00 - 15:06 (01:05)
4. dodohert pts/1 137.48.219.250 Tue Feb 7 12:32 - 12:36 (00:04)
5. dodohert pts/21 137.48.207.237 Tue Feb 7 12:07 - 12:23 (00:16)
6. dodohert pts/11 ip98-168-203-118 Mon Feb 6 20:50 - 23:29 (02:39)
7. dodohert pts/9 ip98-168-203-118 Mon Feb 6 20:31 - 22:57 (02:26)
8. dodohert pts/5 pc-618-012.omhq. Fri Feb 3 10:24 - 10:30 (00:05)
答案 2 :(得分:3)
#!/usr/bin/perl
use strict;
my $hours = 0;
my $mins = 0;
my $loggedIn = 0;
while (<STDIN>)
{
chomp;
if (/\S*\((\d{2,2})\:(\d{2,2})\)\s*/)
{
$hours = $hours + $1;
$mins = $mins + $2;
if($mins >= 60 )
{
$hours = $hours + 1;
$mins = $mins - 60;
}
}
elsif (/still logged in$/)
{
$loggedIn = 1;
}
}
print "Summary: $hours:$mins ", ($loggedIn) ? " (Currently logged in)" : "", "\n";
答案 3 :(得分:1)
当RE无法匹配时,$ 1和$ 2没有值。
出于这个原因,在一个测试RE成功的条件中使用$ 1,$ 2等被认为是最好的做法。
所以不要这样做:
$string =~ m/(somepattern)/sx;
my $var = $1;
但是要做一些像:
my $var = 'some_default_value';
if($string =~ m/(somepattern)/sx){
$var = $1;
}