2017-08-15 33 views
-2

我修改了一個現有的perl腳本,該腳本通過轉到他們的目錄並解析pass,fail或incomplete來檢查某些測試的狀態。我想這個腳本擴展生成包含基於3串的未完成的測試子表:使用grep通過perl查找不同目錄中的文件中的匹配模式

"Error: Failure to checkout svverification license feature." 
"Error: Unable to checkout verification license - required for testbench features" 
"FATAL ERROR: License connection lost and unable to reconnect after multiple attempts." 

每個測試的名字都有自己的目錄,該目錄內是一個名爲vsim.log日誌文件。我可以用grep做這個目錄,但是我認爲將它實現到腳本中會很好,所以每次有不完整的時候我都不必手動grep

該腳本有一個變量$cur_test_name,我將用它來執行此操作,因爲我必須確保進入正確的子目錄。

chdir("/testout/$cur_test_name.1/") or die "Cannot chdir to /testout/$cur_test_name.t"; 
if(system(grep -f "Error: Failure to checkout svverification license feature." vsim.log) or 
system(grep -f "Error: Unable to checkout verification license - required for testbench features" vsim.log) or 
system(grep -f "# FATAL ERROR: License connection lost and unable to reconnect after multiple attempts." vsim.log)) 
{ 
    open($incomplete_tests, '>'; 'incompletes.lst') or die "Cannot open file $!in write mode"; 
    print {$incomplete_tests} $cur_Test_name . "\n";  
    close $incomplete_tests; 
} 
chdir("../../") or die "Cannot chdir to ../../"; 

所以基本上,我想改變目錄到子目錄,並檢查vsim.log文件中存在這些模式。如果他們通過open創建一個新文件(我認爲這是如何完成的),並將測試名稱變量寫入文件。然後關閉文件,然後返回頂層目錄,對每個不完整的測試重複此操作。

但是這不能編譯和Im新的perl,所以我很難找出如何正確使用system()。我已經看到了不同的格式,我見過一些解決方案,只使用grep而沒有system,所以我被卡住了。

我得到的錯誤有以下幾種:

Bareword found where operator expected at bin/run_regress.pl line 1279, near ""Error: Failure to checkout svverification license feature." vsim" 
     (Missing operator before vsim?) 
Bareword found where operator expected at bin/run_regress.pl line 1279, near ""Error: Unable to checkout verification license - required for testbench features" vsim" 
     (Missing operator before vsim?) 
Bareword found where operator expected at bin/run_regress.pl line 1279, near ""# FATAL ERROR: License connection lost and unable to reconnect after multiple attempts." vsim" 
     (Missing operator before vsim?) 
Not enough arguments for grep at bin/run_regress.pl line 1279, near ""Error: Failure to checkout svverification license feature." vsim" 
syntax error at bin/run_regress.pl line 1279, near ""Error: Failure to checkout svverification license feature." vsim" 
Global symbol "$cur_Test_name" requires explicit package name at bin/run_regress.pl line 1282. 
syntax error at bin/run_regress.pl line 1287, near "}" 

編輯:

,我希望把我的代碼是在腳本中的部分地點:

for(my $j=0;$j<$number_of_bfm_based_smoke_100pin_tests;$j++) 
{ 
    chdir("../rtl_mcu_bfm_qfn_100/") or die "Cannot chdir to ../rtl_mcu_bfm_qfn_100"; 
    $curr_test_name = $bfm_based_smoke_100pin_tests[$j] ; 
    process_test_name($curr_test_name); 
    check_status($sim_process_out[1],$bfm_based_smoke_100pin_tests[$j],$seed,"BFM"); 
    $sr_nu++; 
    chdir($start_dir); 
} 

check_status子程序是

sub check_status 
{ 
    my ($pass_fail_string,$cur_test_name,$seed_val,$xdata_mstr) = @_; 
    if ($pass_fail_string =~ /Test FAILED! Test did not end properly/) 
    { 
     # ===== THIS IS WHERE I WANT TO PLACE MY CODE ===== # 
     $incomplete_cnt++ ; 
     printf (STORE_REGRESS_RSLT "|%9d|%78s|%7d|%11s|%12s|\n",$sr_nu,$cur_test_name,$seed_val,"-",$xdata_mstr); 
    } 
    elsif ($pass_fail_string =~ /Test PASSED/) 
    { 
     $pass_cnt++; 
     printf (STORE_REGRESS_RSLT "|%9d|%78s|%7d|%11s|%12s|\n",$sr_nu,$cur_test_name,$seed_val,"PASSED",$xdata_mstr); 
    } 
    elsif ($pass_fail_string =~ /Test FAILED/) 
    { 
     $fail_cnt++; 
     printf (STORE_REGRESS_RSLT "|%9d|%78s|%7d|%11s|%12s|\n",$sr_nu,$cur_test_name,$seed_val,"FAILED",$xdata_mstr); 
    } 
    else 
    { 
     $incomplete_cnt++ ; 
     printf (STORE_REGRESS_RSLT "|%9d|%78s|%7d|%11s|%12s|\n",$sr_nu,$cur_test_name,$seed_val,"-",$xdata_mstr); 
    } 
} 
+3

Perl grep不是系統grep。您必須打開文件並搜索您要查找的行。如果你想使用系統grep,爲什麼不使用bash? – bytepusher

回答

3

首先,沒有理由出去系統爲了搜索文件的模式;處理文件。

接下來,如果你這樣做system是一個錯誤的工具。例如,它不會返回命令的STDOUT,而是返回退出狀態($?)。在這裏你只需要知道是否有出現匹配,而grep出口確實表達了這一點,並被封裝到$?的高位中。感謝ysth的評論。

但是,您的代碼仍然不會看到錯誤,因爲在if下任何非零返回都爲真。您需要分析$?,如果$? >> 8 == 0表示根據grep的手冊頁有匹配。但是,這種方法的效用僅限於grep。另外,如果設計發生了變化,並且您需要輸出(例如,匹配的行),您需要qx(反引號)或其他工具/模塊之一。只需用Perl來完成。

這裏是沿着你想要

use warnings; 
use strict; 
use feature 'say'; 
use Cwd; 

my @dirs = qw(one two three); # my tests, change to suitable names 
my $logfile = 'log.txt';  
my $incomplete_tests = 'incomplete_tests.log'; 
my $curr_test_name = 'current_test'; 

# regex to search with 
my $err_qr = qr/Error: Failure|Error: Unable|FATAL ERROR:/; #/ 

# Open log file for append 
open my $fh_incomp, '>>', $incomplete_tests 
    or die "Can't open to append $incomplete_tests: $!"; 

my $orig_dir = cwd; 
foreach my $dir (@dirs) 
{ 
    chdir $dir or die "Can't chdir to $dir: $!"; 
    my $updated_name = $curr_test_name . "_$dir"; # update as/if needed 

    open my $fh, '<', $logfile or do { 
     warn "Can't open $logfile: $!"; 
     next; 
    }; 

    while (<$fh>) { 
     say $fh_incomp $updated_name if /$err_qr/; 
    } 

    chdir $orig_dir or die "Can't chdir to $orig_dir: $!"; 
} 
close $fh_incomp; 

什麼線工作程序因爲我不明白你的問題全是這個基本的,並與一些猜測。它遍歷目錄列表,檢查每個日誌文件的名稱相同,並且每當一行與預先組成的正則表達式匹配時記錄「測試名稱」與qr operator

您也可以將其更改爲記錄錯誤行(添加打印),或者每個日誌文件只記錄一次測試名稱(匹配後跳至next目錄)。

另請注意,chdir沒有任何理由,因爲您可以輕鬆使用$dir來形成正確的路徑。我使用它來防止您的真實代碼執行更多工作,並且實際上可以從$dir中受益。

還有其他方法可以做到這一點,首先在所有目錄中搜索日誌文件並在每種情況下運行相同的代碼。這可以用File::Find::RulePath::Tiny很好地完成。

+0

但grep的狀態告訴你它是否匹配 – ysth

+0

啊,完全滑倒了!補充一句,謝謝 – zdim

+0

只要跟進一下,你就有'我的@dirs = qw(一二三); '並且你說要把它改成合適的名字,但在我的情況下,有超過一百(在某些情況下數千)測試名稱。在那種情況下我將如何實現它? – Javia1492

相關問題