2

典型的用例是当正则表达式需要包含用户输入时。正则表达式中具有特殊含义的字符(即 Perl 中的“脏打”)需要转义。Perl 提供了“quotemeta”功能来做到这一点:只需将插值变量封装在\Qand中\E。但是 Tcl 没有提供这样的功能(根据这个页面,即使是 ARE)。

在 Tcl 中是否有一个好的(严格的)quotemeta 实现?

4

2 回答 2

3

Perl 的quotemeta函数只是用反斜杠替换每个非单词字符(即,除了 26 个小写字母、26 个大写字母、10 个数字和下划线以外的字符)。这是矫枉过正,因为并非所有非单词字符都是正则表达式元字符,但它简单且安全,因为转义不需要转义的非单词字符是无害的。

我相信这个实现是正确的:

proc quotemeta {str} {
    regsub -all -- {[^a-zA-Z0-9_]} $str {\\&} str
    return $str
}

但是由于 glenn 的评论,这个更好,至少对于现代版本的 Tcl (\W匹配任何在 Tcl 8.0.5 之后的某个时间开始的非单词字符):

proc quotemeta {str} {
    regsub -all -- {\W} $str {\\&} str
    return $str
}

(我假设 Tcl 的正则表达式与 Perl 的足够相似,因此这将在 Tcl 中完成与在 Perl 中相同的工作。)

于 2012-07-11T22:06:29.383 回答
1

我会提出一个解决方案,但我不确定它是否正确。

#
#   notes
#
#   -  "[]" has to appear in the beginning of a character class
#   -  "-" has to come last in a character class
#   -  "#" is not special, but anticipating the x modifier...
#   -  "-" is not special, but anticipating interpolation within "[]"...
#   -  "/" is not special in Tcl
#
proc quotemeta {str} {
    regsub -all -- {[][#$^*()+{}\|.?-]} $str {\\\0} str
    return $str
}
于 2012-07-11T21:57:55.960 回答