如何在TCL中使用regexp来匹配文件中的一行?

如何在TCL中使用regexp来匹配文件中的一行?,tcl,Tcl,我是TCL的新手。因此,我被要求从文件中提取开始日期,但我尝试了,没有输出。请帮忙 从我的文件中,有一行我想提取开始日期: Running final_step.step_done at: Wed Oct 11 02:04:03 MYT 2017 我的代码: proc extract_data {} { ## To extract startdate set file [open files/stages.files] while {[gets $file line]

我是TCL的新手。因此,我被要求从文件中提取开始日期,但我尝试了,没有输出。请帮忙

从我的文件中,有一行我想提取开始日期:

Running final_step.step_done at: Wed Oct 11 02:04:03 MYT 2017
我的代码:

proc extract_data {} {
    ## To extract startdate 
    set file [open files/stages.files]
    while {[gets $file line] >= 0} {
        if {[regexp {^Running (\S+\s)at: (\S+.*)$} $line match Stage StartDate]} {
            if {[regexp "[$CURRENT_STAGE]\.step_done" $Stage]} {
                #set stage $Stage
                                set end_date $StartDate
                set print_end_date [regsub -all " " $StartDate "_"]
                                #echo "2) $stage - $end_date"
            } elseif {[regexp "^[$CURRENT_STAGE] " $Stage]} {
                #set stage $Stage
                set start_date $StartDate
                set print_start_date [regsub -all " " $StartDate "_"]
                #echo "1) $stage - $start_date"
            }
        }
    }

我的regexp有什么问题吗?

主RE看起来很好-
^运行(\S+\S)在:(\S+.*)$
确实与您所说的行匹配-但是这些RE匹配看起来可疑:

regexp "[$CURRENT_STAGE]\.step_done" $Stage
特别是,这里有一个命令替换,命令名来自一个变量。这…在某些情况下是有效的,但这是一项相当先进的技术;你确定这就是你想要的吗?另外,
CURRENT_STAGE
变量似乎未声明。我希望其中一种方法更有可能奏效:

变量替换 这里,我们使用的是变量名的限定版本。请注意,变量最好包含一个有效的正则表达式片段,我们需要将反斜杠加倍(因为我们处于双引号上下文而不是大括号上下文中;一个反斜杠用于基本Tcl语言,另一个用于re引擎)

命令替换 在这里,我们调用一个命令来获取实际的阶段。命令最好返回一个有效的RE片段,和前面一样,我们将反斜杠加倍

regexp "[CURRENT_STAGE]\\.step_done" $Stage

一般来说,在这两种情况下,您可能会考虑在代码< >(.://>代码>…>代码> 中包装代表当前阶段的RE部分,因为这并不能真正改变语义,但这意味着RE片段可以使用安全交互的特征。当重新片段是一个简单的事情,比如
最后一步

时,这并不重要。在我看来,您应该能够用这样的代码完成很多工作:

while {[gets $file line] >= 0} {
    if {[string match Running $line]} {
        set Stage [lindex [split $line] 1]
        set StartDate [lindex [string trim [split $line :]] end]
        if {[string match *.step_done $Stage]} {
            set end_date $StartDate
            set print_end_date [string map {" " _} $StartDate]
        } else {
            set start_date $StartDate
            set print_start_date [string map {" " _} $StartDate]
        }
    }
}
就是

  • 检查该行是否以“Running”开头
  • 将“Running”和“at:”之间的字符串放入
    Stage
  • 获取“:”之后的日期字符串,输入
    StartDate
  • 检查
    $Stage
  • 如果有,请将
    结束日期
    设置为
    $StartDate
    并将
    打印结束日期
    设置为同一字符串,所有空格均替换为下划线
  • 如果尾部为空,则对
    开始日期
    打印开始日期
文件: , , , , , , ,

您要查找的行的开头(和结尾)是否有星号?如果有,
^Running
将与行不匹配。我的代码中没有*。当我将代码设置为斜体时,似乎产生了*。感谢您指出。在第一个
if
之后,尝试输出
阶段
开始日期
变量?我觉得这个问题确实与下一组IF块有关。变量<代码>阶段<代码>捕获阶段描述符和字符串“AT:”之间的空白。下一次调用<代码> ReXEP < /C> >忽略空白(<代码>)[$CurrutyField],StdithOn“”,而<<代码> ELSIF < /C> >(<代码> > [$CurrutyPosi] ] /<代码>没有。如果空白只是将描述符与“AT::string”分隔开来,不要捕获它。其中任何一个都应该有输出,但这肯定会导致问题。
regexp "^$::CURRENT_STAGE " $Stage
regexp "[CURRENT_STAGE]\\.step_done" $Stage
regexp "^[CURRENT_STAGE] " $Stage
while {[gets $file line] >= 0} {
    if {[string match Running $line]} {
        set Stage [lindex [split $line] 1]
        set StartDate [lindex [string trim [split $line :]] end]
        if {[string match *.step_done $Stage]} {
            set end_date $StartDate
            set print_end_date [string map {" " _} $StartDate]
        } else {
            set start_date $StartDate
            set print_start_date [string map {" " _} $StartDate]
        }
    }
}