実行したサイクル数をログ ファイルに出力し続けるプログラムがあります。ログ ファイルの最後の値を取得して、実行されたサイクルの合計数を確認したいと考えています。私は次のコードを使用しています:
my @cycles = $log =~ /\s+(\d+)\s+Cycles/gsm;
$run{cycles} = $cycles[-1] if @cycles;
配列にサイクルを収集する代わりにそれを使用できるように、最後に一致した値を格納する perl の特別な変数はありますか?
これがあなたが望むものだと思います:
my @cycles = $log =~ /\s+(\d+)\s+Cycles/gsm;
$run{cycles} = $+ if @cycles;
squiguyが言ったように、それもうまくいく$1
はずです(少なくとも私にとってはうまくいきます)。
最後に、すべてのサイクルを配列に保存する必要はなく、最後の値だけが必要な場合は、次のようにすることができます。
($run{cycles}) = $log =~ /.+\s(\d+)\s+Cycles/s;
否定先読みアサーションを使用できます。
($run{cycles}) = $log =~ /\s+(\d+)\s+Cycles(?!.*\s+\d+\s+Cycles)/gsm;
意味は、「前に空白があり、その後に空白とリテラルが続く一連の数字を見つけ、その後Cycles
に空白、数字、空白、およびリテラルの別のシーケンスが続かないCycles
」.
ログファイル全体をメモリに読み込むことはお勧めしませんが、何をしているのかについての情報がなければ、適切な行ごとの解決策を書くことはできません.
修飾子を含む正規表現パターンは次の/g
一致で停止するため、必要なのはループだけです。while
/m
または/s
修飾子を使用しても意味がないことに注意してください。これらは、メタ文字の機能を変更するだけなので^
、$
および.
. これらのどれも使用していないため、効果はありません。
while ( $log =~ /\s+(\d+)\s+Cycles/g ) {
$run{cycles} = $1;
}
あなたの質問は不完全です。ログファイルを $log に丸呑みするコードの部分は表示されていません。ログ ファイルの名前が $logFile にあると仮定すると、質問は改善方法です。
my $log = do { local( @ARGV, $/ ) = $logFile ; <> } ;
my @cycles = $log =~ /\s+(\d+)\s+Cycles/gsm;
$run{cycles} = $cycles[-1] if @cycles;
答えは、一度に 1 行ずつログ ファイルを読み取ることです。
open my $logFH,'<',$logFile
or die "Could not open $logFile: $!";
my $cycles;
while (my $logLine = <$logFH>) {
($cycles) = $logLine =~ /\s+(\d+)\s+Cycles/;
}
close $logFH;
$run{cycles} = $cycles
if $cycles;
このようにして、プログラムはファイル全体のスペースではなく $logFile の最長行のスペースのみを使用し、すべての代わりに単一のサイクルを格納するスペースを使用します。
つまり、I/O の量は同じですが、メモリ使用量ははるかに少なくなります。
元のプログラムは次のとおりです。
このプログラムは次のとおりです。
File::ReadBackwards
「最初の」一致する行を使用して取得しないのはなぜですか。
$bw = File::ReadBackwards->new( 'log_file' )
or die "can't read 'log_file' $!"
;
while( defined( $log_line = $bw->readline ) ) {
next unless m/\s+(\d+)\s+Cycles/;
print;
last;
}
それはずっと速くなるはずです。