我有somefile.txt,包含如下行:
{ abc1 } 1
{ cde1 } 101
{ fgh1 } 1
{ ijk1 } 2
它是一个巨大的文件,我想只找到第1行和第3行并计算它们。
我已尝试使用{\s\}\s1\n}
的regexp和lsearch(将其转换为列表),但它不起作用。我该怎么做......?
我也尝试了{\s\}\s1}
,但它打印了所有4行。
答案 0 :(得分:0)
您似乎需要捕获第一行和第三行末尾的数字。
以下是实现这一目标的方法:
set s {{ abc1 } 1
{ cde1 } 101
{ fgh1 } 1
{ ijk1 } 2}
set re {^{[^{}]*}\s*(\d+)\s+{[^{}]*}\s*\d+\s+{[^{}]*}\s*(\d+)}
regexp $re $s m g1 g2
set res [expr $g1 + $g2]
puts $res
请参阅IDEONE demo
模式匹配:
^
- 字符串的开头{[^{}]*}
- 一个{...}
- 类似字符串,里面没有大括号\s*
- 0+ whitespaces (\d+)
- 第1组(g1
)捕获1+位数\s+
- 1+个空格(如果之前和之后不能有尾随/前导空格,则可以用[\r\n]+
替换){[^{}]*}\s*\d+\s+{[^{}]*}\s*(\d+)
- 见上文,只有(\d+)
会创建第二个变量g2
。请参阅regex demo
答案 1 :(得分:0)
如果您不使用正则表达式,这样的问题会更容易解决。
package require fileutil
::fileutil::foreachLine line somefile.txt {
if {[lindex $line end] == 1} {
puts $line
}
}
此解决方案查看文件中的每一行,并检查最后一项是否等于1.如果是,则打印该行。
你也可以统计他们/总结他们:
set count 0
set sum 0
::fileutil::foreachLine line somefile.txt {
if {[lindex $line end] == 1} {
puts $line
incr count
incr sum [lindex $line end] ;# yeah, I know, always 1
}
}
puts "Number of lines: $count"
puts "Sum of items: $sum"
如果您的Tcl安装中没有fileutil
,并且您无法或者不想安装它,您可以使用较低级别的核心等效项:
set f [open somefile.txt]
while {[gets $f line] >= 0} {
if {[lindex $line end] == 1} {
puts $line
}
}
close $f
如果你绝对必须使用正则表达式,在这种情况下你可以这样做:
::fileutil::foreachLine line somefile.txt {
if {[regexp {\m1$} $line]} {
puts $line
}
}
这个正则表达式找到单词中以数字1结尾的行(即它前面没有数字或单词字符)。
文档:close,fileutil包,gets,if,lindex,open,package,{{ 3}},puts,Syntax of Tcl regular expressions,regexp
答案 2 :(得分:0)
解决方案1:如果您不想使用regexp
,并且您的输入行具有与{string} number
相同的格式
set fd [open "somefile.txt" r]
while {[gets $fd line] >= 0} {
if {[lindex $line 1] == 1} {
puts [lindex $line 1] ;# Prints only 1
puts $line ;# Prints Whole Line which has 1 at end
}
}
解决方案2 :如果您要使用regexp
,请转到group-capturing
(.*)
set fd [open "somefile.txt" r]
while {[gets $fd line] >= 0} {
if {[regexp "\{.*\} (.*)" $line match match1]} {
if {$match1 == 1} {
puts $line
}
}
}
解决方案3:基于regexp
上的@Peter建议
set fd [open "somefile.txt" r]
while {[gets $fd line] >= 0} {
if {[regexp {\d+$} $line match]} {
if {$match == 1} {
puts $match ;# Prints only 1
puts $line ;# Prints whole line which has 1 at end
}
}
}