如何将文件拆分为列表列表TCL
我正在编写TCL代码,我想将一个文件拆分为两个列表, 该文件包含:如何将文件拆分为列表列表TCL,tcl,Tcl,我正在编写TCL代码,我想将一个文件拆分为两个列表, 该文件包含: (1,2) (3,4) (5,6) (7,8) (9,10) (11,12) 我想要两份清单 每行一个,包含列表,每个列表包含两个数字 例如: puts $list1 #-> {1 2} {3 4} {5 6} puts [lindex $list1 0] #-> 1 2 puts [lindex $list2 2] #-> 11 12 我尝试使用rege
(1,2) (3,4) (5,6)
(7,8) (9,10) (11,12)
我想要两份清单
每行一个,包含列表,每个列表包含两个数字
例如:
puts $list1 #-> {1 2} {3 4} {5 6}
puts [lindex $list1 0] #-> 1 2
puts [lindex $list2 2] #-> 11 12
我尝试使用regexp和split,但没有成功使用
regexp
的想法很好,但是您需要对其输出进行一些后处理
# This is what you'd read from a file
set inputdata "(1,2) (3,4) (5,6)\n(7,8) (9,10) (11,12)\n"
foreach line [split $inputdata "\n"] {
# Skip empty lines.
# (I often put a comment format in my data files too; this is where I'd handle it.)
if {$line eq ""} continue
# Parse the line.
set bits [regexp -all -inline {\(\s*(\d+)\s*,\s*(\d+)\s*\)} $line]
# Example results of regexp:
# (1,2) 1 2 (3,4) 3 4 (5,6) 5 6
# Post-process to build the lists you really want
set list([incr idx]) [lmap {- a b} $bits {list $a $b}]
}
注意,这是在建立一个数组;长期的经验表明,在循环中构建变量时调用变量list1
,list2
,…,是一个坏主意,应该使用数组,有效地给出变量,如list(1)
,list(2)
,…,因为这样会产生更低的错误率
另一种方法是使用更简单的regexp,然后让
scan
解析结果。当数字不仅仅是数字字符串时,这可能更有效
foreach line [split $inputdata "\n"] {
if {$line eq ""} continue
set bits [regexp -all -inline {\([^()]+\)} $line]
set list([incr idx]) [lmap substr $bits {scan $substr "(%d,%d)"}]
}
如果您没有使用Tcl 8.6,那么您还没有
lmap
。在这种情况下,您可以这样做:
foreach line [split $inputdata "\n"] {
if {$line eq ""} continue
set bits [regexp -all -inline {\(\s*(\d+)\s*,\s*(\d+)\s*\)} $line]
set list([incr idx]) {}
foreach {- a b} $bits {
lappend list($idx) [list $a b]
}
}
您已经有了答案,但实际上可以做得简单一点(或者至少不用
regexp
,这通常是一件好事)
像Donal一样,我假设这是从文件中读取的文本:
set lines "(1,2) (3,4) (5,6)\n(7,8) (9,10) (11,12)\n"
稍微清理一下,删除数据前后的括号和空白:
% set lines [string map {( {} ) {}} [string trim $lines]]
1,2 3,4 5,6
7,8 9,10 11,12
一种使用老式Tcl的方法是,生成一个名为lineN
的变量集群,其中N是一个整数1,2,3…:
set idx 0
foreach lin [split $lines \n] {
set res {}
foreach li [split $lin] {
lappend res [split $li ,]
}
set line[incr idx] $res
}
像这样的双重迭代结构(许多行,每行都有一对由单个逗号分隔的数字)很容易在另一行中使用一个foreach
进行处理。变量res
用于在结果行组装时存储结果行。在最内层,对被拆分并将列表附加到结果。对于每个完成的行,都会创建一个变量来存储结果:其名称由字符串“line”和递增索引组成
正如Donal所说,使用变量集群不是一个好主意。最好将它们收集到一个数组中(除了结果变量的命名方式外,代码相同):
如果在数组中有结果,可以使用parray
实用程序命令一下子列出它们:
% parray line
line(1) = {1 2} {3 4} {5 6}
line(2) = {7 8} {9 10} {11 12}
(请注意,这是打印输出,不是函数返回值。)
您可以从该结果中获得整行:
% set line(1)
{1 2} {3 4} {5 6}
或者,您可以访问配对:
% lindex $line(1) 0
1 2
% lindex $line(2) 2
11 12
如果您有lmap
命令(或链接到下面的替换),您可以稍微简化解决方案(您不需要res
变量):
更简单的方法是将结果设为嵌套列表:
set lineList [lmap lin [split $lines \n] {
lmap li [split $lin] {
split $li ,
}
}]
您可以访问与上面类似的部分结果:
% lindex $lineList 0
{1 2} {3 4} {5 6}
% lindex $lineList 0 0
1 2
% lindex $lineList 1 2
11 12
文件:
,
,
,
,
,
,
,
,
,
,
该代码适用于windows: TCL文件代码为:
proc captureImage{}{
#打开映像配置文件。
设置配置文件[open“C:/main/image\u config.txt”r]
#从配置文件中检索值。
而{![eof$configFile]}{
set part[split[获取$configFile]“=”]
设置道具([string trimright[lindex$part 0]])[string trimleft[lindex$part 1]]
}
关闭$configFile
设置时间[时钟格式[时钟秒]-格式%Y%m%d\uh%m%S]
设置日期[时钟格式[时钟秒]-格式%Y%m%d]
#创建具有当前日期的文件夹
设置folderPath$道具(folderPath)
追加folderDate$folderPath“$date”/
设置FolderCreation[文件mkdir$folderDate]
而{0}{
如果{[file exists$date]==1}{
}
打破
}
#选择相机以捕获图像。
设置摄像机“视频”
附加cctv$摄像机“=”$道具(cctv)
#设置图像分辨率(XxY)。
设置resolutionX$道具(resolutionX)
设置resolutionY$道具(resolutionY)
附加决议$resolutionX“x”$resolution
#将名称设置为保存图像
设置imagePrefix$props(imagePrefix)
设置imageFormat$props(imageFormat)
附加文件名$folderDate“$imagePrefix”“$time”。$imageFormat
设置日志前缀“图像\日志”
附加日志文件$folderDate”“$logPrefix”“$date.txt”
#ffmpeg命令在背景中捕获图像
exec ffmpeg-f dshow-benchmark-i$cctv-s$resolution$filename>和$logFile&
3000后
}
}
captureImage
set idx 0
foreach lin [split $lines \n] {
set line([incr idx]) [lmap li [split $lin] {
split $li ,
}]
}
set lineList [lmap lin [split $lines \n] {
lmap li [split $lin] {
split $li ,
}
}]
% lindex $lineList 0
{1 2} {3 4} {5 6}
% lindex $lineList 0 0
1 2
% lindex $lineList 1 2
11 12