0

有没有办法在正则表达式中使用列表索引?

我已经尝试过,但它不起作用:

if {[regexp {.*\[lindex $mylist 2\].*} $mystring]} {
    puts "OK"
} 

位于名为 mylist 的列表的列表索引 2 处的值不会在正则表达式中替换。

谢谢。

4

3 回答 3

1

我不确定你为什么这样使用正则表达式。你不必匹配整个字符串,你知道吗?

您应该能够使用:

if {[regexp [lindex $mylist 2] $mystring]} {
    puts "OK"
}

请注意,只要字符串中的任何位置存在匹配项,regexp 就会匹配并返回 1。

但是,这可能会给您使用正则表达式元字符带来意想不到的结果。如果[lindex $mylist 2]不包含任何内容,您应该是好的。

除非列表中的元素是正则表达式字符串,否则不会有任何问题。


如果列表元素中有元字符,则可以先使用另一个正则表达式来转义它们:

if {[regexp [regsub -all {[\]\[+*.^${}()?\\]} [lindex $mylist 2] {\\\0}] $mystring]} {
    puts "OK"
}

[regsub -all {[\]\[+*.^${}()?\\]} [lindex $mylist 2] {\\\0}]在元字符中添加反斜杠[\[\]{}()?+*.^$\\](即以下字符[]+{}()?+*.^$\

于 2013-09-15T15:48:46.917 回答
1

如果您只想查看另一个简短的简单字符串是否存在,regexp那不是正确的方法。相反,使用string first

if {[string first [lindex $mylist 2] $mystring] >= 0} {
    puts "OK"
}

如果列表的第三个元素中确实有一个正则表达式,那么这样做就足够了,因为 Tcl 总是检测 RE 是否匹配任何地方(它的模式默认情况下是未锚定的):

if {[regexp -- [lindex $mylist 2] $mystring]} {
    puts "OK"
}

--是为了以防 RE 以-字符开头,这可能会引起混淆。你也可以使用regexp有点像那个string first食谱:

if {[regexp ***=[lindex $mylist 2] $mystring]} {

但是带有的代码string first会更快!如果您想要比这更复杂的事情,最好停下来思考一下您所做的是否是正确的方法;当发现自己在正则表达式中进行复杂的替换时,通常会陷入混乱。(或者至少那是我知道需要重新思考的时候。)在这里提问——同时提供更多的背景信息——可以帮助你弄清楚事情。

于 2013-09-15T16:39:56.720 回答
0

问题是正则表达式中的大括号阻止了对 list 命令的评估。有多种方法可以解决这个问题,其中之一是放弃大括号,并使用允许评估命令的引号。在这种情况下,您需要转义控制字符:

if {[regexp ".*\\[lindex $mylist 2].*" $mystring]} {
    puts "OK"
} 

或者,您可以使用 subst 命令,但这会很冗长:

if {[regexp [subst -nobaclslashes {.*\[lindex $mylist 2\].*}] $mystring]} {
    puts "OK"
} 

我启用了开关的 subst 命令替换了其中的所有内容,除了反斜杠。

于 2013-09-15T15:33:27.810 回答