带有转义字符的 TCL 行解析
TCL line parsing with escape chars
一个观察和一个问题。
给定一个包含转义字符的行的文本文件。 IE。反斜杠。使用 lindex
和 lassign
解析这些行并分隔内容会吃掉转义字符。这是一个半题。我怀疑在 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个主要命令:
regexp -inline
(通常与 -all
一起使用):这几天经常是我最喜欢的,因为我可以描述一个词是什么的 RE 规则,然后让它完成其余的工作我.
split
如果你想要它的作用:有时可以预先设置字符串(使用不常见的 unicode 字符)以使其更好地工作,但我自己不喜欢它。
scan
没有变量:每个人都忘记了这个,包括我自己...
你也可以自己一点一点地做(或者使用处理细节的库函数,比如textutil::splitx
)。
列表操作本身不适用于任意字符串,而是仅适用于那些遵循列表格式规则的字符串。反斜杠在这些规则中很特殊(就像它们在您的脚本中一样)。 {
花括号}
也是如此。通常的建议是不要将任意外部数据视为 Tcl 列表,这是因为它通常适用于测试数据,并且在生产中经常会出现微妙的错误(但不会立即出现)。预清理数据可以省去很多麻烦。
最后我用了正则表达式。它似乎避免了字符串解析并在较低级别上工作以将行分开。
一个观察和一个问题。
给定一个包含转义字符的行的文本文件。 IE。反斜杠。使用 lindex
和 lassign
解析这些行并分隔内容会吃掉转义字符。这是一个半题。我怀疑在 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个主要命令:
regexp -inline
(通常与-all
一起使用):这几天经常是我最喜欢的,因为我可以描述一个词是什么的 RE 规则,然后让它完成其余的工作我.split
如果你想要它的作用:有时可以预先设置字符串(使用不常见的 unicode 字符)以使其更好地工作,但我自己不喜欢它。scan
没有变量:每个人都忘记了这个,包括我自己...
你也可以自己一点一点地做(或者使用处理细节的库函数,比如textutil::splitx
)。
列表操作本身不适用于任意字符串,而是仅适用于那些遵循列表格式规则的字符串。反斜杠在这些规则中很特殊(就像它们在您的脚本中一样)。 {
花括号}
也是如此。通常的建议是不要将任意外部数据视为 Tcl 列表,这是因为它通常适用于测试数据,并且在生产中经常会出现微妙的错误(但不会立即出现)。预清理数据可以省去很多麻烦。
最后我用了正则表达式。它似乎避免了字符串解析并在较低级别上工作以将行分开。