解析tcl中的反斜杠(\)字符

时间:2016-06-13 14:45:12

标签: regex tcl

如何解析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

2 个答案:

答案 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 -exactstring first的工作方式分别为正则表达式和glob-style匹配。

lsearch -regexp

此处的结果为1意味着列表中的第二个元素(索引1)与模式匹配。

(使用lsearch -globset 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 是一种低级别的诡计,以避免字符串表示中的大括号妨碍。)

文档:concatjoinlsearchSyntax of Tcl regular expressionsregexpstring

答案 1 :(得分:0)

您的字符串中包含多个字符,这些字符是regexpstring 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引擎核心的一个特性(共享)。