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

时间:2017-10-13 03:00:47

标签: 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] >= 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"
            }
        }
    }

我的正则表达式有问题吗?

2 个答案:

答案 0 :(得分:1)

主RE看起来很好 - <!DOCTYPE html> <hmtl> <head> <meta charset="UTF-8"> <title>Canvas</title> <style type="text/css"> canvas{ border: 1px solid black; } </style> </head> <body> <canvas id="canvasOne" ></canvas> <script type="text/javascript"> // Gets a handle to the element with id canvasOne. var canvas = document.getElementById("canvasOne"); // Set the canvas up for drawing in 2D. var ctx = canvas.getContext("2d"); canvas.width = 500; canvas.height = 500; function Ball(xpos, ypos, r) { this.xpos = xpos; this.ypos = ypos; this.r = r; this.move = function(addx, addy) { this.xpos = this.xpos + addx; this.ypos = this.ypos + addy; }; this.resize = function(setr) { this.r = setr; }; this.draw = function() { for (var i = 0; i < 7; i++) { ctx.beginPath(); ctx.moveTo(this.xpos, this.ypos); ctx.arc(this.xpos, this.ypos, this.r, i * (2 * Math.PI / 7), (i + 1) * (2 * Math.PI / 7)); ctx.lineWidth = 2; ctx.stroke(); } ctx.beginPath(); ctx.moveTo(this.xpos, this.ypos); ctx.arc(this.xpos, this.ypos, this.r - 10, 0, 2 * Math.PI); ctx.lineWidth = 2; ctx.stroke(); }; this.spin = function() { var angle = 0; this.angle = (this.angle + 1) % 360; ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.save(); ctx.translate(this.xpos,this.ypos); ctx.rotate( this.angle*Math.PI/180 ); ctx.translate(-this.xpos,-this.ypos); ctx.beginPath(); this.draw(); ctx.restore(); }; this.contains = function(x, y) { this.x = this.x; this.y = this.y; if (Math.sqrt((x - this.xpos) * (x - this.xpos) + (y - this.ypos) * (y - this.ypos)) <= this.r) { return true; } else { return false; } }; //put "ball" as a paremeter //ball will be the foreign Ball to test intersection against this.intersect = function(ball) { var productX = this.xpos - ball.xpos; var productY = this.ypos - ball.ypos; var distance = Math.sqrt(productX * productX + productY * productY); if (distance <= (this.r + ball.r)) { return true; } else { return false; } }; } var ball1 = new Ball(100, 100, 100); ball1.draw(); ball1.spin(); setInterval(ball1.spin,100); </script> </body> </html> 确实与你所说的那条线匹配 - 这些RE匹配看起来很可疑:

^Running (\S+\s)at: (\S+.*)$
regexp "[$CURRENT_STAGE]\.step_done" $Stage

特别是,你在那里有一个命令替换,命令的名称来自变量。那是......在某些情况下有效,但是相当先进的技术;你肯定这是你想要的吗?此外,regexp "^[$CURRENT_STAGE] " $Stage 变量似乎未声明。我希望其中一种方法更有可能发挥作用:

可变替换

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

CURRENT_STAGE
regexp "$::CURRENT_STAGE\\.step_done" $Stage

命令替换

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

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

通常,在这两种情况下,您可能会考虑在regexp "^[CURRENT_STAGE] " $Stage ... (?:中包装代表当前阶段的RE部分,因为这并没有真正改变语义,但确实意味着RE片段可以安全地使用交替等功能。当RE片段像)一样简单时,并不重要。

答案 1 :(得分:0)

在我看来,你应该可以用这样的代码完成很多工作:

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]
        }
    }
}

即,

  • 检查该行是否以&#34; Running&#34;
  • 开头
  • 在&#34; Running&#34;之间获取字符串和&#34; at:&#34;进入Stage
  • 在&#34;之后获取日期字符串:&#34;进入StartDate
  • 检查表格中是否有字符串尾部&#34; step_done&#34;在$Stage
  • 之后的一段时间之后
  • 如果有,请将end_date设置为$StartDate,将print_end_date设置为相同的字符串,并将所有空格替换为下划线
  • 如果尾部为空,请对start_dateprint_start_date
  • 执行相同操作

文档: >= (operator)getsiflindexsetsplitstringwhile