2017-07-15 97 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 
        } 
    } 
    
  • 感谢您的帮助!