2017-07-15 54 views
1

我正在嘗試在大文本文件中搜索字符串並相應地返回退出代碼。對於上下文來說,文本文件是ModelSim日誌文件,我需要將1(壞)或0(好)的退出碼傳遞給調用以下TCL腳本(片段)的Windows批處理腳本:TCL字符串匹配不起作用

set sim_pass {# ** Failure: NONE. End of Test: PASS} 
    set sim_fail {# ** Failure: ERRORS. End of Test: FAIL} 
# set each_line "# ** Failure: ERRORS. End of Test: FAIL\r"; 
    set failed_sim 0 

    # Set top-level paths and testbench. 
    global app_sim_path reg_tb_path parent_path log_directory msim_ini 
    set TOP_LEVEL_NAME project_io_tb 

    cd $app_sim_path 

    # Create logfile. 
    set sim_log_file ${parent_path}/${log_directory}/${TOP_LEVEL_NAME}_sim.log 
    if {[file exists $sim_log_file]} { 
    file delete -force $sim_log_file 
    } 
    set fs [open $sim_log_file {RDWR CREAT EXCL}] 
    close $fs 

    # Initialize ModelSim. 
    puts "\[INFO\] Now testing ... $TOP_LEVEL_NAME" 
    vsim -modelsimini $msim_ini -c -quiet -l $sim_log_file 

    # Compile all files required for testbench. 
    source compile.tcl 
    # Log all signals for debug. 
    log -r /* 
    # Run simulation. 
    run -all 
    quit -sim 

    # Read log file. 
    set fptr [open ${sim_log_file} r] 
    set log_data [read $fptr] 
    close $fptr 
    # Split file contents on new line. 
    set line_data [split $log_data "\n"]; 
    # Parse each line. 
    foreach each_line $line_data { 
    # Check if simulation test failed. 
    if {[string match $sim_fail [string trim $each_line]]} { 
     set failed_sim 1 
     break 
    } 
    } 

    # Return correct exit code. 
    if {$failed_sim} { 
    puts "Simulation Failed, returning $failed_sim" 
    } else { 
     puts "Simulation Passed, returning $failed_sim" 
    } 
    exit -code $failed_sim 
    quit -f 

至少2出問題當我執行上面的腳本:

  1. 日誌文件都會以我的Windows命令外殼W/O換行符。如果我在「#讀取日誌文件」之後註釋掉所有內容,則不會發生這種情況。
  2. 即使字符串出現在日誌文件中,退出代碼也爲0。

我在做什麼錯?

[編輯]: 感謝所有的答覆。不幸的是,我仍然無法讓我的TCL腳本工作。這可能與我的日誌文件中包含了我在尋找下面的文本字符串的事實做:

# ** Failure: ERRORS. End of Test: FAIL 

我不能改變文本的第一部分,「#**失敗:」作爲這是ModelSim用於日誌文件的語法。所以「**」可能會搞砸串匹配,因爲我不知道如何逃避它。

我真正想要做的是搜索子字符串「錯誤。測試結束:失敗」,這是我可以改變的文本。

請注意,我正在使用字符串命令在foreach循環中。

我仍然收到整個日誌文件到我的Windows命令窗口的瘋狂長回聲,它也被寫入到沒有換行符的日誌文件中。恐怕我沒有正確打開/關閉日誌文件,所以在我的原始代碼片段中添加了更多內容。

回答

0

第一個問題是由-nonewline造成的。去掉它。

set log_data [read $fptr] 

如果你把它留在,在log_data將不包含換行符,因此split $log_data "\n"將是長度的列表1.

的可能是-code選項exit命令。我找到的文檔表明它不是受支持的選項(沒有選項用於退出)。您之前可能已有過return聲明,其中確實支持-code屬性。嘗試

exit $failed_sim 
+0

-nonewline選項僅刪除最後一個字符,如果它是換行符。所有其他換行符都留在文本中。 –

1

好了,問題與這些模式:

set sim_ok {# ** Failure: NONE. End of Test: PASS}; 
set sim_fail {# ** Failure: ERRORS. End of Test: FAIL}; 

的水珠圖案例如通過string match的支持,你必須整個字符串匹配,甚至後拆分成行可能會有意想不到的字符。那裏可能還有其他一些你不期待的東西(例如,顏色代碼),但最終還是需要匹配的字符。此外,您可能在行尾有空格,並且**以glob模式與*相同並匹配任意數量的任何字符。

診斷提示

您可以通過執行發現這樣的問題:

puts [exec od -c << $the_line_contents] 

,但你要小心這樣做,因爲它大大增加輸出量。這是一個診斷工具,可以讓你準確地看到你的匹配對象,並輕鬆查找不尋常的字符,因爲od -c將任何不可打印的ASCII轉換爲轉義序列並將所有內容分離出來,但它不是你通常會離開的東西在生產中使用。

嘗試這些模式,而不是:

# BTW, you don't need semicolons at the end of the line 
set sim_ok {# * Failure: NONE. End of Test: PASS} 
set sim_fail {# * Failure: ERRORS. End of Test: FAIL} 

,並做模式匹配:

if {[string match $sim_fail [string trim $each_line]]} { 
    ... 

彩色輸出處理(如果這是一個問題)的最簡單的方法是改變在運行生成輸出的程序之前,將TERM環境變量指定爲不支持顏色的內容,例如vt100plain


exit命令不採取-code選項。只需使用直線exit 1即可執行此程序失敗的退出。

0

匹配精確串(不是正則表達式或glob模式),[string first]是一個很好的工具:

set sim_fail {# ** Failure: ERRORS. End of Test: FAIL}; 
set each_line "# ** Failure: ERRORS. End of Test: FAIL\r" ;# trailing whitespace 

if {[string match $sim_fail $each_line]} {puts matched} else {puts "not matched"} 
# => not matched 

if {[string first $sim_fail $each_line] != -1} {puts matched} else {puts "not matched"} 
# => matched 
0

我的TCL腳本的一些調試後,我得到它的工作。該解決方案是:

  1. 添加「悄悄」在我的文件前閱讀:

    quietly set line_data [split [read -nonewline $fptr] "\n"] 
    

這將關閉成績單從ModelSim的,這是我用的是TCL解釋呼應。

  • 固定的 「突破」 命令的縮進和錯位爲以下:

    foreach each_line $line_data { 
        if {[string match $sim_fail $each_line]} { 
         set failed_sim 1 
         break 
        } 
    } 
    
  • 感謝您的幫助!