2017-02-17 12 views
-1

ログファイル内の特定の単語(現在の値=)の後に値を検索し、値を含む文字列を作成したいとします。Perl - ログファイルの値を検索し、文字列として格納/印刷します。

vcs_output.log:ログファイル

** Fault injection ** 
    Count = 1533 
    0: Path = cmp_top.iop.sparc0.exu.alu.byp_alu_rcc_data_e[6] 
    0: Current value = x 
    1: Path = cmp_top.iop.sparc0.exu.alu.byp_alu_rs3_data_e[51] 
    1: Current value = x 
    2: Path = cmp_top.iop.sparc0.exu.alu.byp_alu_rs1_data_e[3] 
    2: Current value = 1 
    3: Path = cmp_top.iop.sparc0.exu.alu.shft_alu_shift_out_e[18] 
    3: Current value = 0 
    4: Path = cmp_top.iop.sparc0.exu.alu.byp_alu_rs3_data_e[17] 
    4: Current value = x 
    5: Path = cmp_top.iop.sparc0.exu.alu.byp_alu_rs1_data_e[43] 
    5: Current value = 0 
    6: Path = cmp_top.iop.sparc0.exu.alu.byp_alu_rcc_data_e[38] 
    6: Current value = x 
    7: Path = cmp_top.iop.sparc0.exu.alu.byp_alu_rs2_data_e_l[30] 
    7: Current value = 1 
    . 
    . 
    . 

私は後に値を格納する場合は、 "現在の値="、その後、X、X、1,0、X、0、X、1。私は最終的にxx10x0x1のような文字列として保存/印刷します。私は1つのループ(あるいはループを使用していない)内の文字列を作るための方法があると思い

#!/usr/bin/perl 

use strict; 
use warnings; 
##### Read input 
open (my $input_fh, '<', 'vcs_output.log') or die $!; 
chomp (my @input = <$input_fh>); 

my $i=0; 
my @arr; 
while (@input) { 
    if (/Current value = /) 
    $arr[i]= $input; # put the matched value to array 
    } 

} 

## make a string from the array using an additional loop 

close ($input_fh); 

は、ここに私のコード code.plです。私にそれをさせるよう助言してください。どんな提案も感謝しています。

use strict; 
use warnings; 

my @arr; 
open (my $input_fh, '<', 'vcs_output.log') or die $!; 
while (<$input_fh>) { 
    if (/Current value = (.)/) { 
     push @arr, $1; 
    } 
} 
close ($input_fh); 
print "@arr\n"; 

__END__ 

x x 1 0 x 0 x 1 
+0

私は以下の答えを受け入れました。ごめんなさい。私は投票しましたが、受け入れることを忘れています –

答えて

1

あなたは、あなたが求めることの両方を行うことができます。

+0

条件式は必要ありません。一致しない正規表現がリストコンテキストで空のリストを返すため、 'my $ string = join ''、map {/ Current * s * value \ s * = \ s *(\ S +)/} <$input_fh>' – Borodin

+0

@Borodinはい、私は思っていました( 'map'の2番目の例) - ' map'で条件を使う方法を示したいと思いました。しかし、あなたのコメントは私が要素を取っていることに気付きました。それは 'map'では必要ではない(更新された)要素だけです。ありがとうございました。 – zdim

+0

@JaeyoungPark "ビット"の意味を説明できますか?あなたはファイルから読み込みます。それぞれの '0,1、x'は_characters_です - それぞれ少なくとも1バイトです。文字列を3〜3文字の文字に分割することを意味しますか?または、8ビットの結果を1バイトとみなし、ビットごとに '0,1、x 'のいずれかをエンコードし、それを3-3-2ビットに分割しますか? (それは他の説明が必要な場合があり、それは別途尋ねるほうがよいかもしれません。) 'x'はどういう意味ですか? – zdim

1

は、あなたがしたい文字列をつかむために括弧をキャプチャすることができます。

はちょうどマッチが $valが空の文字列の後、失敗した場合は、正規表現で

my $string; 
while (<$input_fh>) 
{ 
    my ($val) = /Current\s*value\s*=\s*(.*)/; 
    $string .= $val; 
} 

をキャプチャ何それに追加、直接文字列を構築するために、私たちはテストする必要はありません。また、1つのライン

$string .= (/Current\s*value\s*=\s*(.*)/)[0] while <$input_fh>; 

全体whileループを書くことができますが、それが必要となる理由を私は表示されません。これはファイルハンドルから行ごとに読み込まれることに注意してください。最初にすべての行を配列に読み込む理由はありません。


(明示的な)ループを回避するには、すべての行を読むことができるとmapがリストを必要とするので

my $string = join '', 
    map { (/Current\s*value\s*=\s*(.*)/) ? $1 :() } <$input_fh>; 

として単純に、mapを介してそれらを通過し、ファイルハンドルを返し、リストコンテキストでありますファイル内のすべての行のリスト次に、それぞれがmapのブロック内のコードで処理され、その出力リストが結合されます。

トリックmap { ($test) ? $val :() }はフィルタリングすること、またgrepの仕事をするmapを使用しています - $testが失敗した場合に返される空のリストは、このように消え、出力リストに平坦化されます。ここでの「テスト」は正規表現マッチで、スカラーコンテキストはtrue/falseを返し、キャプチャセットは$1を返します。

しかし、上記のように、マッチが成功したかどうかをテストする代わりに、リターンに一致するリストの最初の要素を返すことができます。我々はmapにあるので、私たちは、実際にここに明確にあるかもしれないもの、「全体」リスト

my $string = join '', 
    map { /Current\s*value\s*=\s*(.*)/ } <$input_fh>; 

を返すことができます。問題のコードの


コメント

  • @inputが枯渇れることは決してありませんので、while (@input)は、無限ループです。 (=を以下では)が、より良いだけでファイルハンドルを読んで、while (<$input_fh>)

  • あなたの正規表現は、その文字列と行の試合を行い、あなたが必要とするパターンに一致しようとしません - あなたはforeach (@input)を必要とするだろう。あなたはそれを追加すると、あなたが(あるべき$i)のi番目の要素に割り当てることができますが、その後、あなたが行くように$iをインクリメントする必要があると思います()

  • により、同様に捕獲される必要があります。時間のほとんどは、それが優れているとちょうどpush @array, $value

0

使用grep
http://perldoc.perl.org/functions/grep.html
http://perldoc.perl.org/perlre.html

perlre、非Unix環境であれば...

#!/usr/bin/perl -w 
use strict; 

open (my $fh, '<', "vcs_output.log"); 

chomp (my @lines = <$fh>); 

# Filter for lines which contain string 'Current value' 
@lines = grep{/Current value/} @lines; 

# Substitute out what we don't want... leaving us with the 'xx10x0x1' 
@lines = map { $_ =~ s/.*Current value = //;$_} @lines; 
my $str = join('', @lines); 

print $str; 

そうでない場合...

#!/usr/bin/perl -w 
use strict; 

my $output = `grep "Current value" vcs_output.log | sed 's/.*Current value = //'`; 

$output =~ s/\n//g; 
print $output; 
関連する問題