如何解析tcl中的反斜杠字符?
我有价值模式" \Q[9]_i_1_n_0
"我想找到包含这种模式的行$line
?我怎么能这样做?
(puts $pattern
返回{\Q[9]_i_1_n_0}
但我使用foreach j [split $pattern]
循环,因此$j
纯粹是\Q[9]_i_1_n_0
)
regexp $pattern $pattern
不起作用:
Error: couldn't compile regular expression pattern: invalid escape \ sequence
lsearch $pattern $pattern
返回-1
string match $pattern $pattern
返回0.
regexp {$pattern} $pattern
返回0
答案 0 :(得分:0)
set pattern {\Q[9]_i_1_n_0}
string first $pattern $pattern
# => 0
与string first
匹配可比较两个字符串的文本内容,而不会为字符赋予任何特殊含义。结果为0意味着在位置0中找到匹配(如果没有匹配,则得到-1)。 string first
不会告诉您是否找到了完全匹配:为此您需要确定结果为0且字符串的长度相同。
通过“glob-style”/“string match”或正则表达式匹配需要考虑那些匹配语言特殊的字符。例如,\
,*
,?
,[
,]
在全局样式匹配中是特殊的,\
,{{1 }},.
,*
,+
,?
,{
,}
,(
,)
,^
在正则表达式匹配中很特殊。在这种情况下,“特殊”意味着例如$
并不意味着“反斜杠”,而是(在两种情况下)都是“逃避”,即一个消除了另一个角色的“特殊性”的角色。这意味着,例如\
表示反斜杠,\\
表示星号。
由于您使用的模式包含\*
,\
和[
,因此需要对模式进行转义,然后才能将模式用于glob样式或正则表达式匹配。 (实际上,通过语法怪癖,关闭转义]
的{{1}}不需要转义。)
转义这些字符的最简单方法之一是使用]
命令执行的字符串转换操作。有人会认为这样做可以解决问题:
[
但由于反斜杠在string map
命令中仍然是特殊的,因此无效。我们需要将地图中反斜杠的数量加倍:
string map {\ \\ [ \[} $pattern ;# error! this code won't work!
现在我们可以尝试使用glob-style / regex匹配:
string map
1的结果意味着布尔真值:找到匹配。请注意,如果有前缀和/或后缀,结果将有所不同:
string map {\\ \\\\ [ \\[} $pattern
这是因为字符串匹配隐式锚定在模式的末尾,而正则表达式需要显式锚定,否则它将忽略前一个或后一个文本。
列表中的匹配类似。 string match [string map {\\ \\\\ [ \\[} $pattern] $pattern
# => 1
regexp [string map {\\ \\\\ [ \\[} $pattern] $pattern
# => 1
的作用类似string match [string map {\\ \\\\ [ \\[} $pattern] abc${pattern}def
# => 0
regexp [string map {\\ \\\\ [ \\[} $pattern] abc${pattern}def
# => 1
,但它只会接受完全相同的字符串。 lsearch -exact
和string first
的工作方式分别为正则表达式和glob-style匹配。
lsearch -regexp
此处的结果为1意味着列表中的第二个元素(索引1)与模式匹配。
(使用lsearch -glob
和set list [concat abc $pattern def]
# => abc \Q[9]_i_1_n_0 def
lsearch -exact $list [join $pattern]
# => 1
lsearch -regexp $list [string map {\\ \\\\ [ \\[} [join $pattern]]
# => 1
lsearch -glob $list [string map {\\ \\\\ [ \\[} [join $pattern]]
# => 1
是一种低级别的诡计,以避免字符串表示中的大括号妨碍。)
文档:concat,join,lsearch,Syntax of Tcl regular expressions,regexp,string
答案 1 :(得分:0)
您的字符串中包含多个字符,这些字符是regexp
和string match
的元字符。特别是,默认情况下,两者都将反斜杠和括号解释为含义。这意味着lsearch
找不到它(或lsearch -glob
),lsearch -regexp
将无效(无效的RE),lsearch -exact
只会找到它整个字符串(没有与lsearch
选项部分匹配的点)。
但你可以通过将regexp
放在模式的前面来覆盖***=
- 样式匹配的行为,提供你正在寻找文字:
set sampleText {this is a sample \Q[9]_i_1_n_0 with the pattern in it}
set pattern {\Q[9]_i_1_n_0}
puts [regexp ***=$pattern $sampleText]
# Prints 1... it matched!
让我们获得一些更好的匹配信息:
puts [regexp -inline -indices ***=$pattern $sampleText]
# {17 29}
看起来对我来说是对的。这也适用于lsearch -regexp
; ***=
技巧是RE引擎核心的一个特性(共享)。