【问题标题】:Tcl regsub: replace a unescapped " with other character '}'Tcl regsub:用其他字符'}'替换未转义的“
【发布时间】:2015-01-23 19:35:09
【问题描述】:

我试图使用regsub 将所有未转义的" 替换为}。我得到了以下内容。

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

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

【问题讨论】:

  • 试试这个正则表达式(?<!\\)\",然后用}替换匹配的字符
  • @AvinashRaj 错误:couldn't compile regular expression pattern: quantifier operand invalid

标签: regex tcl


【解决方案1】:

嗯,您使用的正则表达式并没有真正做到您认为的那样。从字面上看,它会尝试匹配(?!\)"(双引号,前面包含一个反斜杠,带有一个负前瞻)。

让我们试着详细看看事情是如何运作的。我会在赛前和赛后进行抽样,并添加空格以使其更清晰。

a f s d \ " 
       ^

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

a f s d \ "
         ^

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

通常,您需要 lookbehind 来执行您打算执行的操作,因为前瞻无法检查它已经通过的某些内容,但否定的lookbehind 可以做到这一点。不幸的是,tcl 不支持lookbehinds(并且实际上并不需要一个,因为已经有更有效的解决方法)所以最好也匹配转义引号,但单独处理它们(这里将它们完全放回原样是)。

例如,您可以使用类似的东西

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

【讨论】:

    【解决方案2】:

    你必须使用反向引用来达到同样的效果。

    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 & regexp_how_to

    【讨论】:

    • 我的意思不是,我能够得到结果字符串,只是它不是我期望的形式。 \" 不应该改变 dto \},我想跳过转义的 "
    • 更新了我的答案。请检查。
    • 这给出了正确的输出。感谢您提供一种解决方法。但我的主要论坛是了解 (?!re) 类型语法有什么问题以获得所需的输出。
    【解决方案3】:

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

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

    其要点是“将\" 替换为\"(即保持不变),但将" 替换为}”。它看起来很尴尬,因为(在这种情况下)每个字符都需要转义,所以\" 变成了\\\" 等等,但它真的非常简单。

    文档:string

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多