Использование неинициализированного значения $ 1 дополнительно - Perl - PullRequest
2 голосов
/ 08 февраля 2012

Я пишу программу, которая имитирует последнюю команду в UNIX, и я пытаюсь использовать обратную ссылку в своем решении.Моя программа делает именно то, что должна, но я получаю ошибку / предупреждение во время выполнения.У меня вопрос: почему появляется это сообщение об ошибке / предупреждение, и как я могу исправить такую ​​проблему?

Если вам нужна дополнительная информация, которую я могу предоставить.

Выполнение программы

./last dodoherty

OUTPUT

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;
        }
}

Ответы [ 4 ]

10 голосов
/ 08 февраля 2012

Я думаю, что проблема может быть в следующей строке.

1. dodohert pts/1 pc-618-012.omhq. Wed Feb 8 09:19 still logged in

Это потому, что ничто не соответствует шаблону, поэтому $ 1 и $ 2 не определены.

4 голосов
/ 08 февраля 2012

Как было отмечено в других ответах, ваше регулярное выражение не совпадает, и поэтому $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)
3 голосов
/ 08 февраля 2012
#!/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";
1 голос
/ 10 февраля 2012

Когда ваш RE не совпадает, $ 1 и $ 2 не имеют значения.

По этой причине рекомендуется использовать $ 1, $ 2 и т. Д. Внутри условия, которое проверяет успешностьRE.

Так что не делайте:

$string =~ m/(somepattern)/sx;
my $var = $1;

Но вместо этого сделайте что-то вроде:

my $var = 'some_default_value';
if($string =~ m/(somepattern)/sx){
  $var = $1;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...