INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Jobs

TCL basic regexp

TCL basic regexp

(OP)
Hi,

I am trying some regexp, but so far without major success... The thing I want to achieve is the following: having a string:
"-------------------------- some string ----------------------"

I want to check if the string-in-question contains three parts (i.e. heading dashes, then some text and then ending dashes) and if yes, then have the text passed in specific variable, i.e. procedure which returns 1 if string that is passed to it match this regexp and (as second argument) the content of the comment (in the above example 'some string'.

Can you please advise how to achieve this goal ? I tried with something like:

set testString "--------------- check the wheels ----------------"
regexp -- {(-*)(([a-zA-Z0-9]+ )+)(-*)} $testString result dashes1 ans dashes2
puts $result

but that does not work and I cannot split original string into these three sections.

Thanks, Mark

RE: TCL basic regexp

This works:

statusmark.tcl

CODE

set mystring "------ some string ---------" 
set result [regexp {(-+)\s*([^-]*)\s*(-+)} $mystring match first middle rest]

if {$result} {
  puts "String to apply the pattern: '$mystring'"
  puts "result=$result"
  puts "This was matched: '$match'"
  puts "First part (extracted): '$first'"
  puts "First part (extracted): '$middle'"  
  puts "First part (extracted): '$rest'"  
} else {
  puts "Nothing matched !"
} 

Output:

CODE

C:\Work>tclsh85 statusmark.tcl
String to apply the pattern: '------ some string ---------'
result=1
This was matched: '------ some string ---------'
First part (extracted): '------'
First part (extracted): 'some string '
First part (extracted): '---------' 

RE: TCL basic regexp

I have some typos, please correct to

CODE

set mystring "------ some string ---------" 
set result [regexp {(-+)\s*([^-]*)\s*(-+)} $mystring match first middle last]

if {$result} {
  puts "String to apply the pattern: '$mystring'"
  puts "result=$result"
  puts "This was matched: '$match'"
  puts "First part (extracted) : '$first'"
  puts "Middle part (extracted): '$middle'"  
  puts "Last part (extracted)  : '$last'"  
} else {
  puts "Nothing matched !"
} 
Output:

CODE

C:\Work>tclsh85 statusmark.tcl
String to apply the pattern: '------ some string ---------'
result=1
This was matched: '------ some string ---------'
First part (extracted) : '------'
Middle part (extracted): 'some string '
Last part (extracted)  : '---------' 

RE: TCL basic regexp

(OP)
Hi Mikrom,

Thanks a lot - this is exactly what I wanted to achieve :). Still, in order to better understand how it works, can you please clarify the following... ?

1) I believe you make an exact match for dashes (-+) so that it can be associated to $first and $flast. Can you advise if \s* is mandatory to have it working (I tried with (-+)([^-]*)(-+) ) and seems to be working as well) ?

2). Why when I put extra brackets (as far as I know brackets just allow to collect matched regexp to the variable at the very end of the command, i.e. middle) to match middle part (i.e. {(-+)(\s*([^-]*)\s*)(-+)} ) I get as result:
First part (extracted) : '------'
Middle part (extracted): ' some string '
Last part (extracted) : 'some string '
can you please clarify why this approach does not work ?

3) can you confirm that $match will be always equal to $mystring as in this example (as well as any other regexp similar to this one) ?

Thanks,
Mark

RE: TCL basic regexp

1. If you have

CODE

set mystring "------     some string     ---------" 
set result [regexp {(-+)([^-]*)(-+)} $mystring match first middle last] 
then you will get the result with leading spaces

CODE

Middle part (extracted): '     some string     ' 
But when you use

CODE

set mystring "------     some string     ---------" 
set result [regexp {(-+)\s*([^-]*)(-+)} $mystring match first middle last] 
you will get it without leading spaces

CODE

Middle part (extracted): 'some string     ' 
If you are sure that between '----' and 'some string' is minimal one space then you can use

CODE

set mystring "------ some string ---------" 
set result [regexp {(-+)\s+([^-]+)\s+(-+)} $mystring match first middle last] 
which extracts the result without leading and trailing spaces

CODE

Middle part (extracted): 'some string' 


2. What you tried is to extract 4 groups

CODE

set mystring "------ some string ---------" 
set result [regexp {(-+)(\s*([^-]*)\s*)(-+)} $mystring match first middle1 middle2 last]

if {$result} {
  puts "String to apply the pattern: '$mystring'"
  puts "result=$result"
  puts "This was matched: '$match'"
  puts "First    : '$first'"
  puts "Middle1  : '$middle1'" 
  puts "Middle2  : '$middle2'"  
  puts "Last     : '$last'"  
} else {
  puts "Nothing matched !"
} 
it is:

CODE

C:\Work>tclsh85 statusmark.tcl
String to apply the pattern: '------ some string ---------'
result=1
This was matched: '------ some string ---------'
First    : '------'
Middle1  : ' some string '
Middle2  : 'some string '
Last     : '---------' 
with outer brackets

CODE

(\s*([^-]*)\s*) 

it extracts $middle1 with leading spaces and with inner brackets

CODE

(\s*([^-]*)\s*) 
it extracts $middle2 without leading spaces.
Unfortunatelly the trailing spaces will be matched by

CODE

[^-]* 
which means every character except '-', so the marker

CODE

(\s*([^-]*)\s*) 
doesn't have a function here and you can leave it out.

3. $match returns the whole string matched, if it is matched that is if the $result is true

RE: TCL basic regexp

(OP)
Hi,

thank you very much! I believe I now understand how it works in TCL. Great!
Still, struggling with the last element: I am trying to get all occurrences of specific regex and create a list which I could then sort.

My example is the following. I plan to put it all in the list (top element of list would be a row which will contain sub-elements (sub-list) that I will be able to sort further, e.g.
{{1 2 3 ... Gamma} {2 68 108633 ... Beta} {2588 9728 .... Alpha}}

still, by doing regexp (even with -all & -inline) result is different from my expectations (I get not only a subset, but also each and every matching part):

set test {
1 2 3 4 5.55% 6.66% 7.77% 8 Gamma
2 68 108633 0 0.00% 0.00% 0.00% 0 Beta
3 2588 9728 266 11.35% 2.84% 0.62% 0 Alpha
}
set result [regexp -all -inline {([0-9]+)\s*([0-9]+)\s*([0-9]+)\s*([0-9]+)\s*([0-9]+.[0-9][0-9]%)\s*([0-9]+.[0-9][0-9]%)\s*([0-9]+.[0-9][0-9]%)\s*([0-9]+)\s*([A-Za-z\s]*)} $test]

{1 2 3 4 5.55% 6.66% 7.77% 8 Gamma
} 1 2 3 4 5.55% 6.66% 7.77% 8 {Gamma
} {2 68 108633 0 0.00% 0.00% 0.00% 0 Beta
} 2 68 108633 0 0.00% 0.00% 0.00% 0 {Beta
} {3 2588 9728 266 11.35% 2.84% 0.62% 0 Alpha
} 3 2588 9728 266 11.35% 2.84% 0.62% 0 {Alpha
}

(System32) 22 % lindex $result 0
1 2 3 4 5.55% 6.66% 7.77% 8 Gamma

(System32) 23 % lindex $result 5
5.55%

Can you advise what would be the most effective way to achieve the goal (in C I would create a class with all elements as class-fields and a method to sort it, but TCL seems to be working totally different and now I am trying to find the best way to get it done :)).

Thank you for help,
Mark

RE: TCL basic regexp

In your case the result contains a list of matched string and matched variables. You can iterate throught list as follows

CODE

set test {
1 2 3 4 5.55% 6.66% 7.77% 8 Gamma\ 
2 68 108633 0 0.00% 0.00% 0.00% 0 Beta\
3 2588 9728 266 11.35% 2.84% 0.62% 0 Alpha}
set result [regexp -all -inline {([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+)\s+([0-9]+.[0-9][0-9]%)\s+([0-9]+.[0-9][0-9]%)\s+([0-9]+.[0-9][0-9]%)\s+([0-9]+)\s+([A-Za-z]+)} $test]

puts "\$result='$result'"
puts "----------------------------------------------------------------"

set count 1
foreach {match x1 x2 x3 x4 x5 x6 x7 x8 x9} $result {
  puts "\$count = $count:  \$match='$match'"
  puts "\$x1='$x1', \$x2='$x2', \$x3='$x3', \$x4='$x4', \$x5='$x5'"
  puts "\$x6='$x6', \$x7='$x7', \$x8='$x8', \$x9='$x9'"
  puts "----------------------------------------------------------------"
  incr count
} 

Output:

CODE

C:\Work>tclsh85 statusmark2.tcl
$result='{1 2 3 4 5.55% 6.66% 7.77% 8 Gamma} 1 2 3 4 5.55% 6.66% 7.77% 8 Gamma {
2 68 108633 0 0.00% 0.00% 0.00% 0 Beta} 2 68 108633 0 0.00% 0.00% 0.00% 0 Beta {
3 2588 9728 266 11.35% 2.84% 0.62% 0 Alpha} 3 2588 9728 266 11.35% 2.84% 0.62% 0
 Alpha'
----------------------------------------------------------------
$count = 1:  $match='1 2 3 4 5.55% 6.66% 7.77% 8 Gamma'
$x1='1', $x2='2', $x3='3', $x4='4', $x5='5.55%'
$x6='6.66%', $x7='7.77%', $x8='8', $x9='Gamma'
----------------------------------------------------------------
$count = 2:  $match='2 68 108633 0 0.00% 0.00% 0.00% 0 Beta'
$x1='2', $x2='68', $x3='108633', $x4='0', $x5='0.00%'
$x6='0.00%', $x7='0.00%', $x8='0', $x9='Beta'
----------------------------------------------------------------
$count = 3:  $match='3 2588 9728 266 11.35% 2.84% 0.62% 0 Alpha'
$x1='3', $x2='2588', $x3='9728', $x4='266', $x5='11.35%'
$x6='2.84%', $x7='0.62%', $x8='0', $x9='Alpha'
---------------------------------------------------------------- 

RE: TCL basic regexp

Errata: ... result contains a list of matched string and extracted variables

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Resources

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close