带有转义字符的 TCL 行解析

TCL line parsing with escape chars

一个观察和一个问题。

给定一个包含转义字符的行的文本文件。 IE。反斜杠。使用 lindexlassign 解析这些行并分隔内容会吃掉转义字符。这是一个半题。我怀疑在 TCL 中,分配包括目标对象的解析,从而处理转义字符。想知道是否有解决办法。

我的观察是,只有正则表达式能够在不进行处理的情况下将线分开。

我确定论坛文本编辑器会乱码我的测试文件。 (哦,好吧,它没有)

% cat lines.txt
1 a/b/c/d[7]
2 a/b\/c\/d\[7\]
3 a\/b/c/d[7]

set fp [ open lines.txt ]
set rpt [ read $fp ]
close $fp

foreach line [ split $rpt \n ] {
    set val [ lindex $line 0 ]
    set str [ lindex $line 1 ]
    puts "val= $val : str= $str"
}

val= 1 : str= a/b/c/d[7]
val= 2 : str= a/b/c/d[7]
val= 3 : str= a/b/c/d[7]
val=  : str=

foreach line [ split $rpt \n ] {
    lassign $line val str
    puts "val= $val : str= $str"
}

val= 1 : str= a/b/c/d[7]
val= 2 : str= a/b/c/d[7]
val= 3 : str= a/b/c/d[7]
val=  : str=

foreach line [ split $rpt \n ] {
    regexp {(\S+)\s+(\S+)} $line dmy val str
    puts "val= $val : str= $str"
}

val= 1 : str= a/b/c/d[7]
val= 2 : str= a/b\/c\/d\[7\]
val= 3 : str= a\/b/c/d[7]
val= 3 : str= a\/b/c/d[7]

最简单的方法是使用 split 将行分成空白字段,而不是假设它是一个格式正确的 tcl 列表。

foreach line [ split $rpt \n ] {
    lassign [split $line " "] val str
    puts "val= $val : str= $str"
}

如果这不起作用,因为字段之间可以有多个空白字符,您可以使用 splitx,它在正则表达式而不是简单字符上拆分:

package require textutil::split
foreach line [ split $rpt \n ] {
    lassign [textutil::split::splitx $line] val str
    puts "val= $val : str= $str"
}

任意字符串解析为列表有3个主要命令:

  1. regexp -inline(通常与 -all 一起使用):这几天经常是我最喜欢的,因为我可以描述一个词是什么的 RE 规则,然后让它完成其余的工作我.
  2. split 如果你想要它的作用:有时可以预先设置字符串(使用不常见的 unicode 字符)以使其更好地工作,但我自己不喜欢它。
  3. scan 没有变量:每个人都忘记了这个,包括我自己...

你也可以自己一点一点地做(或者使用处理细节的库函数,比如textutil::splitx)。


列表操作本身不适用于任意字符串,而是仅适用于那些遵循列表格式规则的字符串。反斜杠在这些规则中很特殊(就像它们在您的脚本中一样)。 {花括号}也是如此。通常的建议是不要将任意外部数据视为 Tcl 列表,这是因为它通常适用于测试数据,并且在生产中经常会出现微妙的错误(但不会立即出现)。预清理数据可以省去很多麻烦。

最后我用了正则表达式。它似乎避免了字符串解析并在较低级别上工作以将行分开。