Tcl regsub:替换未加掩盖的“与其他角色'}'

时间:2015-01-23 05:42:04

标签: regex tcl

我尝试使用regsub将所有未加盖的"替换为}。我得到了以下内容。

% set st {hello "hi this athat afsd\" adsfasdf"}
% regsub -all {(?!\\)\"} $st \}
hello }hi this athat afsd\} adsfasdf}

我想要的是什么 hello }hi this athat afsd\" adsfasdf}。请告诉我出了什么问题。

3 个答案:

答案 0 :(得分:1)

你必须使用反向引用来实现相同的目标。

set st {hello "hi this athat afsd\" adsfasdf"}
puts $st
regsub -all {([^\\])"} $st \\1\} result
puts $result

<强>输出:

hello "hi this athat afsd\" adsfasdf"
hello }hi this athat afsd\" adsfasdf}

文档:regsub man page&amp; regexp_how_to

答案 1 :(得分:1)

嗯,你正在使用的正则表达式并没有真正按照你的想法去做。从字面上看,它会尝试匹配(?!\)"(双引号与前面包含一个反斜杠的负前瞻)。

让我们试着详细了解事情是如何运作的。我将在比赛前后采样,增加空格以使其更清晰。

a f s d \ " 
       ^

这里引擎向前看并看到反斜杠。由于前瞻性为负,匹配失败,因此继续使用字符串。

a f s d \ "
         ^

现在它通过了反斜杠,它试图再次进行匹配。前方没有反斜杠,因此负前瞻不会阻止匹配。接下来,正则表达式尝试匹配成功的双引号。

通常,你需要一个 lookbehind 来做你想要做的事情,因为前瞻不能检查它已经传递的东西,但是负面的后视就是这样。不幸的是,tcl不支持lookbehinds(并且实际上不需要一个,因为已经有更高效的变通方法)所以最好匹配转义的引号,但是单独处理它们(这里将它们放回原来就像它们一样均)。

例如,您可以使用类似

的内容
 regsub -all {(\\")|"} $st {\1} result

答案 2 :(得分:1)

如果您要重新考虑使用regsub,使用string map命令可以更简单地进行此转换:

string map {\\\" \\\" \" \}} $st

它的要点是&#34;将\"替换为\"(即保持不变),但将"替换为}&#34;。它看起来很尴尬,因为(在这种情况下)每个角色都需要被转义,所以\"变成\\\"等等,但它真的非常简单。

文档:string