2

I'm trying to extract the specific lines from a trace file like below:

- 0.118224 0 7 ack 40 ------- 1 2.0 7.0 0 2
r 0.118436 1 2 tcp 40 ------- 2 7.1 2.1 0 1
+ 0.118436 1 2 ack 40 ------- 2 3.1 2.1 0 3
- 0.118436 1 2 ack 40 ------- 2 4.1 2.1 0 3
r 0.120256 0 7 ack 40 ------- 1 2.0 7.0 0 2

I want to extract any line that have the following:

r x.xxxxx 1 2 xxx xx ------- x numbers.x 2.x x x.

Note: x means any value and numbers could be between 3-to-7.

here is my try-its not working !!:

if {[regexp \r+ ([0-9.]+) 1 2.*-  ([3-7.]+) 2.*- ([0-9.]+) $line -> time]} 

Any suggestion??

SimpleNEasy
  • 879
  • 3
  • 11
  • 32
  • 2
    Always enclose the `if` condition in braces: `if {[regexp ...]} {...}` – glenn jackman Apr 19 '13 at 17:38
  • And enclose the regexp in braces too: `if {[regexp {\r...} $line -> time]} {...}` – Johannes Kuhn Apr 19 '13 at 20:42
  • Enclosing the RE in braces is just _usually_ a good idea; putting the condition in braces is _really_ a good idea (unless it is a literal like `0` or `true`, in which case it's not making a difference) because it helps ensure that the `if` itself gets bytecode compiled. – Donal Fellows Apr 20 '13 at 11:51
  • Did you mean `r x.xxxxxx 1 2 xxx xx ------- x numbers.x 2.x x x`? (I added another `x` to make the long series of numbers 6 characters long instead of 5 in your post) – Jerry Apr 20 '13 at 13:00

2 Answers2

0

You have to escape the . with a \. It means "any character" in regexp.

So your regexp could look like:

if {[regexp {r \d\.\d{5} 1 2 \d{3} \d{2} ------- \d [3-7]\.\d 2\.\d \d \d} $line -> time ]} {
   # ...
}

Now you have to place () around the part you want.

Btw: I used the following transformation on your description of what you want to match:

set input {r x.xxxxx 1 2 xxx xx ------- x numbers.x 2.x x x}
set re [subst [regsub -all {x{2,}} $data {\\\\d{[string length \0]}}]]
set re [string map {. {\.} x {\d} numbers {[3-7]}} $re]
Johannes Kuhn
  • 14,778
  • 4
  • 49
  • 73
  • 1
    I'd go for `^r \S\.\S{5} 1 2 \S{3} \S{2} ------- \S [3-7]\.\S 2\.\S \S \S$` myself (and possibly use the `-line` option) but that's just minor variation. – Donal Fellows Apr 20 '13 at 11:49
0

Here's another approach: extract the fields you want to use for comparison

while {[gets $f line] != -1} {
    lassign [split $line] a - b c - - - - d e - -
    if {
            $a eq "r"  && 
            $b == 1    && 
            $c == 2    && 
            3 <= floor($d) && floor($d) <= 7  && 
            floor($e) == 2
    } {
        puts $line
    }
}
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
  • It's not printing other values when d=3,4,5,6. It only prints the first value when d=7. !!! – SimpleNEasy Apr 19 '13 at 21:05
  • @SimpleNEasy Are you trying this on your sample? Remember that only the 2nd line is supposed to match because of the other restrictions. I tried it too and it works. – Jerry Apr 20 '13 at 12:58