1

Is it possible to dynamically add flags to a command, without using eval?

For example, I wish to perform the following with a variable:

set isCaseSensitive 1
if {$isCaseSensitive == 1} {
    set res [regexp -nocase -- $regexp $str]
} else {
    set res [regexp -- $regexp $str]
}

# The following does NOT work

set regexp_flags ""
if {$isCaseSensitive == 1} {
    append regexp_flags " -nocase"
}
set res [regexp $regexp_flags -- $regexp $str]

Using Tcl 8.5


Edit #1, 12:41 UTC:
(Response to the commenter Jerry)

I've executed the code:

set regexp_flags ""
if {$isCaseSensitive == 1} {
    append regexp_flags "-nocase"
}

set res [regexp -line -all -inline -indices $regexp_flags -- $regexp $str]

And received the following error (omitted irrelevant text):

regexp match variables not allowed when using -inline
    while executing
"regexp -line -all -inline -indices $regexp_flags -- $regexp $str"

That happens because that Tcl thinks that $str is a 4th parameter, which is forbidden while using the -inline flag.

See regexp command documentation.


Edit #2, 14:01 UTC:

Apparently for some reason, the non-printable characters that are in my subject string ($str) have some negative effect on this command. (Tcl isn't binary protected or something?)
I've tried to delete those characters before trying to regexp and it now works as expected.

set regexp_flags ""
if {$isCaseSensitive == 1} {
    append regexp_flags "-nocase"
}

set str [regsub -all -- {[^[:print:]\t\n\r\f\v]} $str ""]
set res [regexp -line -all -inline -indices $regexp_flags -- $regexp $str]
6
  • 2
    Why not simply append regexp_flags "-nocase"? It's working on my Tcl8.5. (inserting the space made it no more work) Commented Jan 2, 2014 at 9:19
  • @Jerry: Plz see my first edit. Commented Jan 2, 2014 at 12:48
  • Variables refer to captured groups. I'm having no problem whatsoever... Here's a demo and it's running fine on 8.4. Commented Jan 2, 2014 at 12:54
  • @Jerry I've found the reason to my problem. See my 2nd edit. Thx! :) Commented Jan 2, 2014 at 14:04
  • I just noticed your edit :) No problem! Commented Jan 2, 2014 at 14:05

1 Answer 1

1

In 8.5 and 8.6, the best way to this sort of thing is:

set regexp_flags ""
if {$isCaseSensitive == 1} {
    lappend regexp_flags -nocase
}

set res [regexp -line -all -inline -indices {*}$regexp_flags -- $regexp $str]

In 8.4 (and before, in case you're really old school!) you needed this construction instead (and you definitely need the second [list …] because the RE and string are unlikely to be neat barewords):

set regexp_flags ""
if {$isCaseSensitive == 1} {
    lappend regexp_flags -nocase
}

set res [eval [list regexp -line -all -inline -indices] $regexp_flags [list -- $regexp $str]]

Though that is perhaps better written as:

set regexp_cmd [list regexp -line -all -inline -indices]
if {$isCaseSensitive == 1} {
    lappend regexp_cmd -nocase
}

set res [eval $regexp_cmd [list -- $regexp $str]]

Wouldn't you rather use 8.5? Or put (?i) at the front of the RE (which also makes it case-insensitive)?

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.