如何将文件拆分为列表列表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

我正在编写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

我尝试使用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