Reputation: 1674
I have this file :
#2/1/1/21=p1 5/1/1/21=p1 isid=104
3/1/1/9=p1 4/1/1/4=p1 5/1/1/17=p1 6/1/1/4=p1 isid=100
1/1/1/4=p1 6/1/1/5=p1 isid=101
I want line 1 to be ignored (it a commented line) In line two I want to get "3/1/1/9" "4/1/1/4" "5/1/1/17" in three variables var1 var2 and var3 In line three I want to get "1/1/1/4" and "6/1/1/5" in two variables var1 and var2.
For the moment I can ignore line 1, and match what I want on line 2 OR line 3 :
if {[regexp {^(\d/\d/\d/\d{1,2})=p1.*(\d/\d/\d/\d{1,2})=p1} $line value match1 match2]} {
# This works for line 3 but not line 2
}
if {[regexp {^(\d/\d/\d/\d{1,2})=p1.*(\d/\d/\d/\d{1,2})=p1.*(\d/\d/\d/\d{1,2})=p1} $line value match1 match2 match3]} {
# This works for line 2 but not line 3
}
How can I have the right number of matched for line 2 AND 3 ?
Upvotes: 1
Views: 122
Reputation: 246837
This might be better:
lassign [regexp -all -inline {\d+(?:/\d+){3}(?==p1)} $line] var1 var2 var3
If there are only 2 matches, var3 will be empty
If there are more matches, only the first 3 will be captured in variables.
If you really just want all the matches:
set vars [regexp -all -inline {\d+(?:/\d+){3}(?==p1)} $line]
To ignore comments:
while {[gets $fh line] != -1} {
if {[regexp {^\s*#} $line]} continue
# do your other stuff here ...
}
Upvotes: 1
Reputation: 71538
Try this regex:
[regexp {^(\d/\d/\d/\d{1,2})=p1.*?(\d/\d/\d/\d{1,2})=p1(?:.*?(\d/\d/\d/\d{1,2})=p1)?} $line value match1 match2 match3]
^^^ ^^
This makes the third match optional.
I also turned your greedy .*
into non-greedy .*?
.
To get all matches, you could use something more like this:
if {[string range $line 0 0] ne "#"} {
set matches [regexp -all -inline -- {\d/\d/\d/\d{1,2}(?==p1)} $line]
}
And you will get the matches in the list $matches
. You can then access them through lindex
or if you use lassign
and give them specific names.
Upvotes: 2
Reputation: 6070
try this:
(^|\s)(\d/\d/\d/\d=p1)
or more compactly:
(^|\s)((\d/){3}\d=p1)
Upvotes: 0