2012-02-08 5 views
2

私は、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; 
     } 
} 
+0

がどこに定義されない$ 1と$ 2? – Pluckerpluck

+3

@Pluckerpluck '$ 1'と' $ 2'は通常の変数ではなく、読み込み専用の変数で、最後に成功した正規表現のキャプチャグループのマッチを含みます。 – TLP

+1

あなたは '\ d {2,2}'と言う必要はありません。あなたは '\ d {2}'と言うことができます。また、 '$ hours = $ hours + $ 1'は' $ hours + = $ 1'と書くほうが良いでしょう。 – zgpmax

答えて

10

問題は次の行にある可能性があります。何もので、$ 1と$ 2が定義されていないパターンに一致しないためである

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

。他の回答で指摘したように

+0

うわー、あなたはそれが非常に論理的な解決策のように聞こえると言いました。私はこれを修正して報告します! – Trance339

+0

ありがとう、私はそれをifステートメントに加えました、そして、私はもうエラーを取得しません。私はそれが非常に単純な問題であることを知っているが、これは私の最初のperl/regexプログラムであり、私は助けてくれてありがとう! – Trance339

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"; 
+0

私は、複数の理由でパターンマッチを 'if'で常にラップすることに同意します。別のものを見ることができます:http://stackoverflow.com/questions/4045467/perl-match-outside-if-doesnt-reset-1-on-loop –

+1

'$ hours、$ mins、$ isloggedIn'を初期化する必要はありません代わりに '+ ='を使用すると(警告を避けるため)。 'chomp'は必要ではありません。行末は決して使用されません。 – TLP

4

、あなたの正規表現は一致していないので、$1$2は未定義です。これらの変数を使用する前に、適切な正規表現が一致することを常に確認する必要があります。

以下、適切なperlコードでスクリプトをアップグレードしました。この場合、+=%=は便利な演算子です。あなたはそれらについて読むことができますperlop

あなたの正規表現は\S*\s*を使います。あなたの正規表現は他のものに固定されていないので、ここでは全く必要ありません。つまり、\S*foo\s*は、fooの空の文字列と一致する可能性があるため、fooを含む文字列と一致します。また、{2,2}は、少なくとも2回、最大2回マッチすることを意味し、実際には{2}「マッチ2回」と同じです。

$minsは決して120より高くはないと仮定しているので、私はあなたの数学を変更したことがわかります。これは安全上の前提ですが、以下のようにすると、すべての値を処理できます成功して数時間にすることができます。

以下のスクリプトはデモ用です。

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) 
+0

説明のおかげで非常に助かりました(アップアップしますが、私は15人のXDが必要です)。私はあなたの提案をクラスの後半で考慮に入れます。 – Trance339

1

あなたのREが一致しなかった今までに、$ 1と$ 2がありません持っている場合は、あなたがDATAを削除し、<>を残す場合はそのようなものであるとして、あなたは、このスクリプトを使用することができます値。

このため、REの成功をテストする条件の中に$ 1、$ 2などを使用することが常にベストプラクティスと考えられています。

そうしません。

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

しかし、その代わりのようなものを行うに:

my $var = 'some_default_value'; 
if($string =~ m/(somepattern)/sx){ 
    $var = $1; 
} 
関連する問題