正则表达式在 Tcl 中不匹配带有 [] 和 / 的字符串
Regexp not matching string with [] and / in Tcl
我无法将正则表达式与具有 /
和 []
模式的引脚名称相匹配。如何在 tcl regexp 中用这个表达式匹配字符串?
问题:
% set inst "channel/rptrw12\[5\]"
channel/rptrw12[5]
% set pin "channel/rptrw12\[5\]/rpinv\[11\]/vcc"
channel/rptrw12[5]/rpinv[11]/vcc
% regexp -nocase "^$inst" $pin
0
通过案例:
% regexp -nocase vcc $pin
1
% set pat "ctrl/crdtfifo"
ctrl/crdtfifo
% set pin2 "ctrl/crdtfifo/iwdatabuf"
ctrl/crdtfifo/iwdatabuf
% regexp -nocase $pat $pin2
1
如果您还记得正则表达式,[]
语法在正则表达式中具有特殊含义。它定义了一个字符组。例如:
[abc]
表示匹配a
或b
或c
.
因此模式:
channel/rptrw12[5]
表示匹配字符串:
channel/rptrw125
如果你想匹配正则表达式中的文字字符 [
你需要将它转义(与正则表达式中有意义的所有其他字符相同,如 .
或 ?
或 (
等)。所以你的模式应该是:
channel/rptrw12\[5\]
但请记住,字符 \
和 [
在 tcl 字符串中具有特殊含义。所以你的代码必须做:
set inst "channel/rptrw12\\[5\\]"
第一个 \
转义了 \
字符,以便 tcl 将单个 \
插入到字符串中。第三个 \
转义 [
字符,这样 tcl 就不会尝试执行名为 5
.
的命令或函数
或者你可以使用 {}
而不是 ""
:
set inst {channel/rptrw12\[5\]}
你的问题是你正在与 RE 引擎元字符作斗争,特别是 […]
,它定义了一个字符集。如果您想继续使用当前的方法,则需要添加更多反斜杠。
但你不必那样做!
如果你问的是“这个字符串是否存在于那个字符串中?”您也可以考虑使用其中之一:
使用string first
并检查结果(子串所在的位置)是否为负数:
if {[string first $inst $pin] >= 0} {
puts "Found it"
}
使用regexp ***=
,意思是“将其余部分解释为文字字符串,没有元字符”:
if {[regexp ***=$inst $pin]} {
puts "Found it"
}
如果您只想匹配字符串开头的相等性(您问的是“这个字符串 start 是否与那个字符串相同?”)您可能应该改为其中之一:
使用string first
并检查结果索引是否为零:
if {[string first $inst $pin] == 0} {
puts "Found '$inst' at the start of '$pin'"
}
使用 string equal
和正确的选项(非常类似于 C 中的 strncmp()
,如果你知道的话):
if {[string equal -length [string length $inst] $inst $pin]} {
puts "'$pin' starts with '$inst'"
}
我无法将正则表达式与具有 /
和 []
模式的引脚名称相匹配。如何在 tcl regexp 中用这个表达式匹配字符串?
问题:
% set inst "channel/rptrw12\[5\]"
channel/rptrw12[5]
% set pin "channel/rptrw12\[5\]/rpinv\[11\]/vcc"
channel/rptrw12[5]/rpinv[11]/vcc
% regexp -nocase "^$inst" $pin
0
通过案例:
% regexp -nocase vcc $pin
1
% set pat "ctrl/crdtfifo"
ctrl/crdtfifo
% set pin2 "ctrl/crdtfifo/iwdatabuf"
ctrl/crdtfifo/iwdatabuf
% regexp -nocase $pat $pin2
1
如果您还记得正则表达式,[]
语法在正则表达式中具有特殊含义。它定义了一个字符组。例如:
[abc]
表示匹配a
或b
或c
.
因此模式:
channel/rptrw12[5]
表示匹配字符串:
channel/rptrw125
如果你想匹配正则表达式中的文字字符 [
你需要将它转义(与正则表达式中有意义的所有其他字符相同,如 .
或 ?
或 (
等)。所以你的模式应该是:
channel/rptrw12\[5\]
但请记住,字符 \
和 [
在 tcl 字符串中具有特殊含义。所以你的代码必须做:
set inst "channel/rptrw12\\[5\\]"
第一个 \
转义了 \
字符,以便 tcl 将单个 \
插入到字符串中。第三个 \
转义 [
字符,这样 tcl 就不会尝试执行名为 5
.
或者你可以使用 {}
而不是 ""
:
set inst {channel/rptrw12\[5\]}
你的问题是你正在与 RE 引擎元字符作斗争,特别是 […]
,它定义了一个字符集。如果您想继续使用当前的方法,则需要添加更多反斜杠。
但你不必那样做!
如果你问的是“这个字符串是否存在于那个字符串中?”您也可以考虑使用其中之一:
使用
string first
并检查结果(子串所在的位置)是否为负数:if {[string first $inst $pin] >= 0} { puts "Found it" }
使用
regexp ***=
,意思是“将其余部分解释为文字字符串,没有元字符”:if {[regexp ***=$inst $pin]} { puts "Found it" }
如果您只想匹配字符串开头的相等性(您问的是“这个字符串 start 是否与那个字符串相同?”)您可能应该改为其中之一:
使用
string first
并检查结果索引是否为零:if {[string first $inst $pin] == 0} { puts "Found '$inst' at the start of '$pin'" }
使用
string equal
和正确的选项(非常类似于 C 中的strncmp()
,如果你知道的话):if {[string equal -length [string length $inst] $inst $pin]} { puts "'$pin' starts with '$inst'" }