我需要编写一个tcl脚本来处理文本文件的行。该文件看起来像
10.77.33.247 10.77.33.241 rtp 0x26
10.77.33.247 10.77.33.241 rtp 0x26
10.77.33.247 10.77.33.241 rtp 0x26
10.77.33.247 10.77.33.241 0x24
10.77.33.247 10.77.33.241 0x22
10.77.33.247 10.77.33.241 0x21
我需要能够遍历文件,并且对于包含rtp
的每一行,在变量中存储其后面的值(例如,上面示例中的0x26
)才能使用在剧本的其他部分。
答案 0 :(得分:3)
这是一种(相当低级别的)Tcl方式。
set ch [open myfile.txt]
set data [chan read $ch]
chan close $ch
set lines [split [string trim $data] \n]
set res {}
foreach line $lines {
if {[llength $line] > 3 && [lindex $line 2] eq {rtp}} {
lappend res [lindex $line 3]
}
}
如果将“myfile.txt”替换为数据文件的名称并运行此代码,则会在变量res
中获得您收集的单词。
通常最好在glenn jackman的答案中使用标准(内置或tcllib)命令,例如fileutil::foreachLine
。但是,如果一个人想要一步一步地做,Tcl仍然很容易。
第一步是将文件内容放入内存。这也有一个标准命令:fileutil::cat
,但以下序列将执行:
set ch [open myfile.txt]
set data [chan read $ch]
chan close $ch
(这或多或少等同于set data [fileutil::cat myfile.txt]
。)
下一步是将文本拆分为行。修剪文本两端的空格总是一个好主意,否则松散的换行符会产生干扰处理的空元素。
set lines [split [string trim $data] \n]
在某些情况下,我们可能不得不将这些行拆分为字段列表,但是从示例中可以看出这些行已经可以用作列表(只有空格,字母数字和行为符合标点的行如点通常是)。
我们需要对匹配线进行测试。有几种替代方案适合您提供的示例数据,包括
string match *rtp* $line ;# match every line that has "rtp" somewhere
[llength $line] > 3 ;# match every line that has more than three columns
[lindex $line 2] eq {rtp} ;# match every line where the third element is "rtp"
我们还需要一种方法来提取我们想要的数据。如果“rtp”之后的单词始终位于最后一列,[lindex $line end]
将完成此任务。如果该单词始终位于第四列,但可能还有其他列,则[lindex $line 3]
更好。
抓住其中几个替代方案,可以编写获得指定单词列表的程序
set res {}
foreach line $lines {
if {[llength $line] > 3 && [lindex $line 2] eq {rtp}} {
lappend res [lindex $line 3]
}
}
(在伪代码中:获取一个空列表(res
);测试每一行(使用上面两个测试的组合),从每个匹配行中提取所追求的单词并将其添加到res
列表。)
或使用lmap
(Tcl 8.6 +)
set res [lmap line $lines {
if {[llength $line] > 3 && [lindex $line 2] eq {rtp}} {
lindex $line 3
} else {
continue
}
}]
“rtp”字后面的所有单词现在应该在res
中。如果你只是想要最后一场比赛,那就是[lindex $res end]
。
文档:chan,continue,foreach,if,lappend,lindex,llength,{{3 }},lmap,open,set,split
答案 1 :(得分:0)
假设您的文件是foo.txt:
grep "word" foo.txt
答案 2 :(得分:0)
grep" 0x26" file.txt的 将显示其中包含0x26的所有行。
答案 3 :(得分:0)
tcllib有很多优点:
% package require fileutil
1.14.5
% fileutil::foreachLine line "file" {
if {[string match {*rtp*} $line]} {
lappend values [lindex [split $line] end]
}
}
% puts $values
0x26 0x26 0x26
答案 4 :(得分:0)
以下代码适用于从文件夹中获取文本(""):
proc aifWebcamInitVideo {} {
variable devicePath "c:/testfile.txt"
#ffmpeg command to get the device name connected to system
exec ffmpeg -list_devices true -f dshow -i dummy >& $devicePath &
after 4000 ;# wait of 4 seconds so that device can be selected.
set files [glob $aif::LogRootDir/*] ;# Look for all the files.
foreach file $files {
set fileName $devicePath
if {[string match $fileName $file ] } { ;# this if statement check currently captured video with the files present in directory.
set file [open $devicePath ] ;# open the file
set file_device [read $file]
set data [split $file_device "\n"] ;# divides the open file into lines.
foreach line $data {
if {[regexp {"([^""]*)"} $line -> substring]} { ;# check for the quotes to retrieve the device connected to system.
set result $substring
lappend cameraList $result ;# makes the list of devices.
set camera [lindex $cameraList 0]
}
}
close $file
break
}
}
#values passed to FFMPEG command.
variable TableCamera $camera
puts "Device selected for Video capture is : $TableCamera" ;# gets the first device from the list
}