0
votes

I am trying to find multiple string patterns in a string in TCL. I cannot get the correct and optimized way to do that.

I have tried some code and it is not working

I have to find -h ,-he,-hel ,-help in the string -help

set args "-help"
set res1 [string first "-h" $args] 
set res2 [ string first -he $args] 
set res3 [string first -hel $args]
set res4 [string first "-help" $args"]

if { $res1 == -1 || $res2 || $res3 || $res4 } {
   puts "\n string not found"
} else {
  puts "\n string found" 
}

how to use regexp here I am not sure , so need some inputs.

The expected output is

1
Welcome, Vyan. The snippet you posted is not valid, there is an excessive or unmatched double quote. Also, your question is not clear to me. Each string first does find the patterns you show, and returns the matching starting index into the haystack string (which is always 0 in your example, because, well, each pattern matches starting with index 0). So, what is the problem? - mrcalvin

1 Answers

1
votes

This is a case where using regexp is easier. (Asking if a string is a prefix of -help is a separate problem.) The trick here is to use ? and (…) (or rather (?:…) which is the non-capturing version) in the RE and you must use the -- option because the RE begins with a -:

if {[regexp -- {-h(?:e(?:lp?)?)?} $string]} {
    puts "Found the string"
} else {
    puts "Did not find the string"
}

If you want to know what string you actually found, add in a variable to pick up the overall match:

if {[regexp -- {-h(?:e(?:lp?)?)?} $string matched]} {
    puts "Found the string '$matched'"
} else {
    puts "Did not find the string"
}

If you instead want the indices where it matched, you need an extra option:

if {[regexp -indices -- {-h(?:e(?:lp?)?)?} $string match]} {
    puts "Found the string at $match"
} else {
    puts "Did not find the string"
}

If you were instead interested in whether the string was a prefix of -help, you instead should do:

if {[string equal -length [string length $string] $string "-help"]} {
    puts "Found the string"
} else {
    puts "Did not find the string"
}

Many uses of this sort of thing are actually doing command line parsing. In that case, the tcl::prefix command is very useful. For example, tcl::prefix match finds the entry in a list of options that a string is a unique prefix of and generates an error message when things are ambiguous or simply don't match; the result can be switched on easily:

set MY_OPTIONS {
    -help
    -someOtherOpt
}
switch [tcl::prefix match $MY_OPTIONS $string] {
    -help {
        puts "I have -help"
    }
    -someOtherOpt {
        puts "I have -someOtherOpt"
    }
}